The Artima Developer Community
Sponsored Link

Weblogs Forum
A case for member literals in Java

18 replies on 2 pages. Most recent reply: Nov 27, 2007 11:22 AM by Clark Updike

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 18 replies on 2 pages [ 1 2 | » ]
Ian Robertson

Posts: 68
Nickname: ianr
Registered: Apr, 2007

A case for member literals in Java (View in Weblogs)
Posted: Nov 3, 2007 11:05 PM
Reply to this message Reply
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.


John Cowan

Posts: 36
Nickname: johnwcowan
Registered: Jul, 2006

Re: A case for member literals in Java Posted: Nov 4, 2007 3:27 PM
Reply to this message Reply
Umm, you are aware that the compiler translates String.class into Class.forName("java.lang.String")?

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: A case for member literals in Java Posted: Nov 4, 2007 4:59 PM
Reply to this message Reply
> Umm, you are aware that the compiler translates
> String.class into Class.forName("java.lang.String")?

The important difference is that Class.forName("java.lang.Sting") compiles, but Sting.class does not.

Ian Robertson

Posts: 68
Nickname: ianr
Registered: Apr, 2007

Re: A case for member literals in Java Posted: Nov 4, 2007 9:17 PM
Reply to this message Reply
> Umm, you are aware that the compiler translates
> String.class into Class.forName("java.lang.String")?

Really? According to javap, String.class translates to:

0: ldc_w #2; //class java/lang/String

while Class.forName("java.lang.String") translates to

0: ldc #3; //String java.lang.String
2: invokestatic #4; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;

That said, the main point is not any gains in runtime efficiency, but the gains in compile-time checking.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: A case for member literals in Java Posted: Nov 5, 2007 9:18 AM
Reply to this message Reply
> Really? According to javap, String.class
> translates to:

IIRC, older versions of Java did insert the call to Class.forName(String).

This is a pretty good idea, I think. The more I think about it, the more I feel this does address a particular clumsiness of Java. It would eliminate a lot of boilerplate without the ugliness and verbosity of (Java) reflection.

Tom Haggie

Posts: 2
Nickname: thos
Registered: Nov, 2006

Re: A case for member literals in Java Posted: Nov 5, 2007 10:10 AM
Reply to this message Reply
This is something I've wanted for a long time too, though I'm not sure I like your syntax. I'd prefer to keep . separators for readability, if a special deliminator is needed I think I'd prepend the special character:

private EqualsHelper<Person> equalsHelper = EqualsHelper.create(
Person.class,
#Person.firstName,
#Person.lastName);

The text of the post doesn't explicitly mention it but this should cover methods as well - so I could call:

aMethodImCalling(#myPerson.aNormalMethod)

aMethodImCalling(#Person.aSta ticMethod)

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

O.K., I'm confused Posted: Nov 5, 2007 11:59 AM
Reply to this message Reply
According to Google, there is no EqualsHelper.create(). Nor is there a non-static myEqualsHelper.equals() method (in the Hibernate EqualsHelper, the only one I could find), only a static method. So I have no idea just what this proposal proposes.

Also, a question on annotations, Does GuardedBy mean that access should be guarded, or can it somehow enforce that access actually is guarded??? If the former, adding a language feature just to avoid typos in what is effectively a comment, seems a bit extreme. And there are far more good instances of bad comments to tackle. :-)

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: O.K., I'm confused Posted: Nov 5, 2007 1:58 PM
Reply to this message Reply
> According to Google, there is no EqualsHelper.create().
> Nor is there a non-static myEqualsHelper.equals() method
> d (in the Hibernate EqualsHelper, the only one I could
> find), only a static method. So I have no idea just what
> this proposal proposes.

I think some example code for EqualsHelper would be a good idea but I think I have a grasp on what this feature does.

The idea is basically a way to do typesafe reflection in Java. It would almost be like have a method pointer or pointer to a field. The equals helper would take the input fields and create an instance that would take two instances of Person and look up the fields in those Person instance to compare them.

You could build this right now using the reflection APIs. The difference would be that the compiler could check that the named fields are actually members of the Person class and of the proper types for the expressions they are used in.

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: O.K., I'm confused Posted: Nov 5, 2007 3:10 PM
Reply to this message Reply
Thanks James. Don't forget that EqualsHelper must also do hashCode!!!

Catching it in the compiler is nice, but if any of your unit test code, or manual testing, ever calls equals that will catch the typo. I'm far from a TDD fanatic, but this "problem" strikes me as unlikely to happen given any amount of reasonable testing.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: O.K., I'm confused Posted: Nov 5, 2007 5:37 PM
Reply to this message Reply
> Thanks James. Don't forget that EqualsHelper must also do
> hashCode!!!
>
> Catching it in the compiler is nice, but if any of your
> unit test code, or manual testing, ever calls equals that
> will catch the typo. I'm far from a TDD fanatic, but this
> "problem" strikes me as unlikely to happen given any
> amount of reasonable testing.

Sure but you get all the dependency information and the refactoring etc. etc.

Personally, I like this idea because there are things that I could do with this that I can't bring myself to do with reflection. It's just too hard to read and for that reason, in combination with the lack of typechecking makes it unmaintainable.

Ian Robertson

Posts: 68
Nickname: ianr
Registered: Apr, 2007

Re: O.K., I'm confused Posted: Nov 5, 2007 8:03 PM
Reply to this message Reply
> Also, a question on annotations, Does GuardedBy mean that
> access should be guarded, or can it somehow enforce
> that access actually is guarded??? If the former,
> adding a language feature just to avoid typos in what is
> effectively a comment, seems a bit extreme. And there are
> far more good instances of bad comments to tackle. :-)

It means the former. However, tools such as FindBugs can work with the annotation to do static code analysis to see if the annotations claim appears to be true. Of course, if there is a typo, FindBugs will likely catch it, but a type-safe mechanism will also play nicely with refactoring, code completion and the like.

Jordan Zimmerman

Posts: 23
Nickname: jordanz
Registered: Jul, 2003

Re: A case for member literals in Java Posted: Nov 6, 2007 10:24 AM
Reply to this message Reply
This is an excellent idea. I have another use-case. We have a home-built O/R framework. One of the APIs allows specifying columns for the WHERE clause of the query. Currently, it takes a String name. But, a member literal would be much better and much safer.

Akhilesh Mritunjai

Posts: 1
Nickname: mritun
Registered: Oct, 2005

Re: A case for member literals in Java Posted: Nov 6, 2007 10:59 AM
Reply to this message Reply
Umm, As per Java Language Specification v2, Annotations *cannot* do any of the following:

1) Cause an otherwise correct and valid code to not compile.
2) Change semantics of a correct code.
3) Affect correctness and validity of code

Thus using an @GuardedBy would be a violation of the language standard as it does affect the correctness of the Java Code.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: A case for member literals in Java Posted: Nov 6, 2007 11:40 AM
Reply to this message Reply
> Umm, As per Java Language Specification v2, Annotations
> *cannot* do any of the following:
>
> 1) Cause an otherwise correct and valid code to not
> compile.

Doesn't the @Override annotation violate that rule?

Wilfred Springer

Posts: 176
Nickname: springerw
Registered: Sep, 2006

Re: A case for member literals in Java Posted: Nov 6, 2007 12:52 PM
Reply to this message Reply
I like it. I have plenty of cases in which this would be really useful.

Flat View: This topic has 18 replies on 2 pages [ 1  2 | » ]
Topic: A case for member literals in Java Previous Topic   Next Topic Topic: Python 3000 alpha 1 Released!

Sponsored Links



Google
  Web Artima.com   

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