Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't understand @ConstructorProperties

About @ConstructorProperties

Documentation says "An annotation on a constructor that shows how the parameters of that constructor correspond to the constructed object's getter methods". And it gives an example which is ambiguous because variable names are identical to parameters.

I really don't get why @ConstructorProperties({"x", "y"}) refers to getters getX() and getY(). Case of x and y are not consistent with annotation.

So to clarify what should be the annotation for the constructor in this code:

public class Point {
    public Point(int a, int b) {
       this.c = a;
       this.d = b;
   }

   public int getCc() {
       return c;
   }

   public int getDd() {
       return d;
   }

   private final int c, d;

}

(I edited the code because from the answer, I understand the annotation expects the code to follow common case convention for getters, e.g. cc getter must be getCc(). But I keep on purpose, for disambiguation, the difference between getter name and actual variable returned)

Second question...

@ConstructorProperties(value="text")

What does this annotation means, for JButton(String text)?

It seems provided for use by tools, but just want to understand.

like image 443
mins Avatar asked Nov 02 '14 19:11

mins


1 Answers

@ConstructorProperties is used by some serialization frameworks to associate constructor parameters with corresponding fields and their getter and setter methods.

To do this, it relies on the same common naming conventions that is used when naming getter and setter methods for fields: Getter and setter method names are usually created by capitalizing the field's name and prepending the prefixes get or set (or is for a boolean getter). The example with single letter field names isn't the best to show this though.

A better example: someValue becomes getSomeValue and setSomeValue

So in the context of constructor properties, @ConstructorProperties({"someValue"}) means that the first parameter is associated with the getter getSomeValue and the setter setSomeValue.

Keep in mind that method parameter names aren't visible at runtime*. It's the parameters' order that counts. The names of constructor parameters or which fields are actually set by the constructor don't matter. The following would still refer to a method named getSomeValue().

@ConstructorProperties({"someValue"})
public Point(int a) {
    this.c = a;
}

When is this annotation required?

JavaBeans usually have a public default constructor (with no arguments) and public getter and setter methods for all fields. This means they are easy to serialize without any annotations but also that they are always mutable.

The use case for @ConstructorProperties seems to be deserialization of objects that don't follow the JavaBeans convention, for example immutable POJOs that don't have any setters:

For serialization, the framework gets all values using the objects getter and uses these values to serialize the object. When the object needs to be deserialized, the framework has to create a new instance. Because the object is immutable, it doesn't have any setters though that could be used to set its values. The constructor is the only way to set those values. The annotation is used to tell the framework how to call the constructor to initialize the object correctly.


* As pointed out in the comments, JEP 118 which was released with Java 8, can be used to include parameter names at runtime. This optional feature could make annotations like @ConstructorProperties obsolete, but only if the framework supports that feature.

like image 200
kapex Avatar answered Oct 19 '22 17:10

kapex