The Artima Developer Community
Sponsored Link

Code by Any Other Name
A case for member literals in Java
by Ian Robertson
November 4, 2007
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 ClassNotFoundExceptions). 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;

the @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.

Talk Back!

Have an opinion? Readers have already posted 18 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Ian Robertson adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

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.

This weblog entry is Copyright © 2007 Ian Robertson. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use