dagblog.
← Archive

Even more static


I’m a big fan of dynamic languages over what I see as forcibly extending Java, but some proposals have my sympathy. One is JSR 308: Annotations on Java Types, which aims to allow annotations to be declared on almost any use of a type.

JSR 308 proposes an extension to Java’s annotation system that permits annotations to appear on nearly any use of a type. (By contrast, Java SE 6 permits annotations to appear only on class/method/field/variable declarations; JSR 308 is backward-compatible and continues to permit those annotations.) Such a generalization removes arbitrary limitations of Java’s annotation system, and it enables new uses of annotations

This language extension would make it possible, for example, to build a powerful annotation processor for advanced checking of type information. The following example illustrates it best.

01 @NonNullDefault 

02 class DAG {

03 

04 Set edges; 

05 

06 // ...

07 

08 List getNeighbors(@Interned @Readonly Vertex v) @Readonly { 

09 List neighbors = new LinkedList();

10 for (Edge e : edges) 

11 if (e.from() == v) 

12 neighbors.add(e.to()); 

13 return neighbors; 

14 }

15 }

(Note that the annotations themselves aren’t part of the specification. See the explanation.)

  • The @NonNullDefault annotation on line 1 says none of the class’s variables may be null. That applies to lines 4, 10, 11, and 12. The return value of getNeighbors also may not be null.
  • The two @Readonly annotations on line 8 guarantee that the method argument v will not be modified and that calling getNeighbors will not change the state of the object.
  • The Interned annotation on line 8 says that use of the object equality operator on line 11 is valid.

That’s the semantics of the annotations. Now imagine the compiler enforcing all those restrictions for you. How can it check them? Because you can put annotations in those places in the first place (more examples of placement). Then you just need to write an appropriate annotation processor to check them and hook it into the compiler.

On this subject I recommend the very interesting presentation Preventing bugs with pluggable type-checking, which shows the possibilities opened up by the specification. Of course there are other uses for declaring annotations this widely. API documentation comes to mind, for example.

One effect of expanding where annotations can be used would certainly be more complex code and a shift toward the static side (of the Force ;-). On the other hand, what other syntax extensions can you simply ignore if you want to? For me, the example of enhanced compile-time type checking is a strong argument for this proposal.

Related articles

Medium version

Related articles

Related CZ Podcast episodes