In the great Java property debate, a lot of rather exotic ideas have been put forward. Using a new ‘property’ keyword; using an arrow (->) or at-sign (.@) or even a pound-sign to include null-safe access.[1] Me, I don’t get it. Sure, getters and setters make for lines and lines of repetitive code and they’re annoying to browse through. But at least they don’t get in the way when I’m coding, like the lack of closures does–to name just one thing.
So my contribution to the debate will be a conservative one, even if it is inspired by Ruby. It will not conflict with existing code or syntax. It will not use new keywords or exotic ascii characters. It will not use annotations to generate code (but it will use annotations). It will not include null-safe access. It will not get rid of getters and setters. So what will it do?
In a Ruby class, fields can be specified using one of three methods, like this:
class Person
attr_accessor :lastname
attr_reader :firstname
attr_writer :age
end
After instantiating an object of this class, we can access the properties using just their names, like this:
person = Person.new
person.lastname = "Doe"
print person.firstname
person.age = 44
Even though it looks as if you’re directly using the fields, these are actually method calls. That’s right, Ruby allows you to skip parentheses on method calls, so you’re really doing this:
person.lastname=("Doe")
print person.firstname()
So where did these methods come from? They’re dynamically inserted into the class definition at runtime by the attr_accessor, attr_reader and attr_writer methods. Internally, the class can reference its fields as self.lastname
. That’s how Ruby discriminates between field and corresponding method. Need a custom getter or setter? You can always define the generated method explicitly, in which case it will not be generated for you.
My Properties Proposal For Java
So how can all this revolutionary stuff lead to a conservative proposal for Java properties? As Java is not dynamic, it cannot insert methods at runtime. So how about we let the compiler insert them at compile time, in the compiled class? All you have to do yourself is declare the field–and by default, the compiler will generate a getter and setter method. How would that work out?
It will not conflict with existing code. If you already have getters and setters in your class, they will not be generated for you. I would suggest adding a compiler option to enable the generation. If you do not use the option, you do not get the generated methods. So existing code will compile and result in the same classes as they did before. Only if you do use the option, you get the new behaviour.
It will use annotations–but not to generate code. Because the code will be generated anyway. But you could use annotations to parameterize the generation. We could have an annotation to generate just a getter or just a setter. There could also be an annotation to toggle special behaviour in the methods (fire an event?). And how about an class-level annotation to turn generation on or off for all fields in that class?
It will not use new keywords or exotic ascii characters. It will not get rid of getters and setters. Getters and setters will still be there–you just won’t have to write them yourself anymore, or have your IDE insert them, or have to browse through them. Sure, you don’t get to use that cool new arrow sign. All the more reason to support the closure proposal, which has an even cooler fat arrow sign.
It will not include null-safe access. Of course it won’t. What did you think, that the compiler would do everything for you?
And now for the obligatory fantasy code sample:
public class Person {
// Will generate getter and setter:
private String lastname;
// Will generate getter:
@FieldReader protected String firstname;
// Will generate setter:
@FieldWriter public Integer age;
public static void main(String args[]) {
Person p = new Person();
// Use the generated methods:
p.setLastname("Doe");
p.getLastname();
p.getFirstname();
p.setAge(44);
}
}
@FieldAccess(access=NO_ACCESS)
public class Address {
// Will not generate anything because of class-level annotation:
private String street;
}
29-01-07 UPDATE: I have put this proposal on javap.info.
[1] Am I the only one who dislikes this language-design-by-ascii?
— “We need a new language feature!”
— “O don’t worry, we’ve got all these weird-looking characters that we can still use. How about the €-sign? It looks like an ‘e’, maybe we can use it to check if a collection is empty?”