![]() |
Sponsored Link •
|
Summary
Allowing static references to class members could greatly increase Java's type-safe expressive capability.
Advertisement
|
I recently ran across First-class
methods: Java-style closures by Stephen Colebourne and Stefan
Schulz. The second section in particular, "Member Literals", caught
my eye as suggesting something which I have been wishing Java had for
awhile. Since Java 1.0, we've been able to
name classes in our source code, e.g. String.class
. Of
course, we can also say
Class.forName("java.lang.String")
, but this is both less
elegant and more error prone (and hence also requires coding for
ClassNotFoundException
s). Once we have a class, however,
we can go no further without abandoning static typing; to refer to a
class's members requires reflection.
It doesn't have to be this way. Already, whenever a class directly accesses a member of another class, that member reference is stored in the referring class's constant pool. Allowing member literals in Java code would greatly add to Java's ability to be expressive in a type-safe manner, especially with annotations. Colebourne and Schulz propose using Javadoc-style syntax to accomplish just this.
For example,
consider the GuardedBy
annotation from Brian Goetz's Java Concurrency In Practice.
This annotation is meant to be placed on a field to indicate what lock
must be acquired before accessing the field. The annotation takes a
single string value with documented semantics.
@GuardedBy("mutex")
implies that a lock should be
acquired on the mutex
field,
@GuardedBy(Foo.bar)
implies that a lock should be
acquired on the static field bar
in the class
Foo
, and so forth. Thus in the following code:
public class Worker {
private Object runningMutex = new Object();
@GuardedBy("runningMutex")
private boolean running;
@GuardedBy
annotation expresses the intent that all
accesses to running
should take place while holding a
synchronization lock on runningMutex
. Unfortunately, if
there were a typo, say the value passed to @GuardedBy
was
"runnningMutex"
, the compiler would not catch this. If
the @GuardedBy
annotation was just meant to be used by a tool like FindBugs, the
problem will be caught soon enough. However, if one was hoping to use
some runtime byte code manipulation to enforce the access policy, a
runtime error would occur.
Using Colebourne and Schulz's "Member Literals" proposal, the above code could be rewritten as:
public class Worker {
private Object runningMutex = new Object();
@GuardedByField(Worker#runningMutex)
private boolean running;
The benefits would not be limited to annotations. For example, one could write something like:
public class Person {
private String firstName;
private String lastName;
private EqualsHelper<Person> equalsHelper = EqualsHelper.create(
Person.class,
Person#firstName,
Person#lastName);
@Override public boolean equals(Object obj) {
return equalsHelper.equals(this, obj);
}
While member literals do not dramatically increase the expressiveness of Java over the current methods of just using strings, they do dramatically increase the type safety of those expressions. Method and field constants would be readily understood by refactoring tools and the like. Similarly, IDEs would be able to provide good code completion support for them.
Have an opinion? Readers have already posted 18 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Ian Robertson adds a new entry to his weblog, subscribe to his RSS feed.
![]() | Ian Robertson is an application architect at Verisk Health. He is interested in finding concise means of expression in Java without sacrificing type safety. He contributes to various open source projects, including jamon and pojomatic. |
Sponsored Links
|