JDK-6432147 : Add Annotation-based support for defensive coding practices
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-05-31
  • Updated: 2011-02-16
  • Resolved: 2006-05-31
Related Reports
Duplicate :  
Description
A DESCRIPTION OF THE REQUEST :
It is common good practice to code defensively so that, for example: when returning a state of an object which is a collection, you wrap that collection in an "unmodifiable" layer. In user-developed code, it is frequently the case that user defined Objects should sometimes be passed around in a "look-but-don't-touch" form. I believe that the Annotation framework introduced in JDK5 allows us to provide "native" support in Java for this programming model.

I would declare 3 Annotations in the java.lang package

---- Mutator Annotation ------------

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Mutator { }

---- End Mutator -----

The mutator annotation would declare that an operation (method) on an Object was state-changing.

---- Immutable annotation --------

@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface Immutable {}

----- End class -----

The immutable annotation would indicate to the compiler that the parameter/field/local variable was Immutable. That is, a compiler error/warning would result if one were to call a method annotated with @Mutator on such a parameter/field/variable.

---- ReturnsImmutable Annotation ----

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface ReturnsImmutable {}

---- Ends ReturnsImmutable ----

The ReturnsImmutable annotation would declare whether the object returned by either a Constructor (or more likely a method) should be treated as Immutable.

RULES:

1). You cannot assign a non-Immutable field/variable/parameter to a Immutable field/variable/parameter. For example, suppose myMethod has a parameter myParam which is un-annotated

@Immutable Object myObject = new SomeObject();
Object hisObject = myObject;

Would result in an error/warning, as would

myMethod(myObject); //as the signature of myMethod did not declare its parameter as @Immutable


2). You cannot assign a non-Immutable variable/field/parameter to the result of a method marked @ReturnsImmutable. Suppose myMethod() is marked as such:

Object myObject = myMethod();

Would result in an error/warning

3). The annotations @ReturnsImmutable and @Mutator should work similarly to thrown Exceptions in terms of method overriding. That is, a superclass or interface declaring a method as @Mutator should not mean that sub-classes/interfaces need override the method as a @Mutator.

4). The annotations @ReturnsImmutable and @Mutator should work similarly to thrown Exceptions in terms of implementations inheriting identical method signatures from one or more interfaces. That is, the sub-classes must annotate only the intersection of the super-interface annotations

JUSTIFICATION :
This enhancement is necessary from the perspective of allowing the developer to inform the compiler of his/her intentions. The Immutability/mutability of Objects is a fundamental part of application development and the more the compiler can help enforce developer intentions, the more robust Java would be as a language to support application-development.

The Annotations would reduce the need for developers to split out interfaces into immutable and mutable (ie. the mutable interface extending the immutable interface adding the mutators).

Although I could develop my own annotation-processing framework to achieve these goals, I think that the feature would be beneficial to the Java language and would also require expertise in understanding language compilation which I may lack!

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An example with returning unmodifiable Lists etc.

I would ensure that the add, addAll, clear, remove and removeAll methods from the List interface were all to be annotated with @Mutator.

Collections.java

@ReturnsImmutable
public static List unmodifiableList(List list) { return list; }

...and usage

@Immutable List list = Collections.unmodifiableList(myList);

...or more simply

@Immutable List list = myList;