Using static methods instead of public constants being .clone()

I just noticed a recent checkin of jME files where most of the calls to constant fields for things like Vector3f and ColorRGBA were appended with a  .clone(), presumably so that clients could utilize those constant fields but then modify them in the future without effecting globally everyone who made an initial reference to that object.



e.g.



Old


        origin = (Vector3f)capsule.readSavable("origin", Vector3f.ZERO);



New


        origin = (Vector3f)capsule.readSavable("origin", Vector3f.ZERO.clone());



So I was thinking that instead of a constant field perhaps just use a static method that clones the constant (which could be made a private final static field) so that no one would be able to change it, and it would preserve the immutability of those defined constants and be less error prone (although i guess you lose performance if you had an application that wanted to share those constants and could guarantee they'd never change them).

E.G.


public class Vector3f implements Externalizable, Savable {
...
   private final static Vector3f ZERO = new Vector3f(0, 0, 0);

   public static Vector3f ZERO() {
      return ZERO.clone();
   }
...
}

Yes, that is a good suggestion for post 1.0

Actually, you're not really supposed to use clone anymore.  :stuck_out_tongue:



Is there any reason why:


public static Vector3f ZERO() {
    return ZERO.clone();
}



Is considered better than:

public static Vector3f ZERO() {
    return new Vector3f(0.0f, 0.0f, 0.0f);
}



I would think the later would likely even be faster.

we override clone to do exactly what you are doing in the second method.  It would be (mostly) the same to your compiler aside from member accesses.  But yeah, either way it's a wait.

I would not remove public access to those constants. It is nice being able to use common constant values without having to allocate new memory for them. Often you don't use them in a modifying manner anyway.



Instead, why not create new subclasses that throw exceptions if the user tries to modify them?

For example:

public static Vector3f ZERO = new Vector3f() {
    {
        x = 0; y = 0; z = 0;
    }
    Vector3f set(float x, float y, float z)
    {
        throw new OperationNotSupportedException("This constant value must not be modified, use a copy instead.");
    }
    ....
}



Of course, one could not use the clone() method for copying, but a new copying method or copy constructor must be used to copy these instances.