Const function arguments in java?

12.6k views Asked by At

Is there a way to achive something similar to C++'s const in Java? Specifically, I have a function like

private static Vector2 sum(Vector2 vec1, Vector2 vec2) {
    return vec1.cpy().add(vec2);
}

and I want to

  1. make clear in the signature that it doesn't modify it's arguments,
    and
  2. enforce that it doesn't modify it's arguments (preferably at compile time, but inserting runtime assertions would also be OK).

Now I know that java is strictly pass-by-reference (I'm just teasing, I know it is pass-by-value or rather pass-by-copying-a-reference of course). What I mean is that in Java, when you call a method, the reference is copied, but that reference points to the same object contents. If a class has public fields or setters, a called method can always modify the contents of a passed object. Is there any e.g. annotation like @NotNull or tool to prevent this? I just found the JetBrains annotations like @Contract(pure = true), but I don't think they provide any checking.

3

There are 3 answers

2
Orest Savchak On

You can not guarantee that method won't change the parameters. If you want to avoid changing the object, you should make it immutable. You can use some wrapper classes to be passed inside, without provided setters. Or you can make your setters package-local and use some access helper classes in the same package if you need to call some package-local method.

0
AxelH On

You can add final to the parameter, but this will only prevent a initialisation of those, you still can call method and setter modifying the content of your Vector.

If you need the restrict the access to those, you might need to create a immutable class hiding the Vector, a wrapper. Basicly it will redirect only the methods that prevent any update by hiding the setter and limit the getter to primitive values, returning an instance give a possibility to change a value in it.

Of course, there is also some drastic solution, you could clone the Vector and his content. Keeping the instances safe even if someone try to update some values. This will only be a problem during this call, using wrong values but will keep the original instances unchanged.

Or you could use both solution, creating a wrapper that return cloned instance (just need to provide a get(int index) that return a clone). This solution is a compromise between memory consumption (cloning only needed instance) and restrictive getter.

0
Peter Lawrey On

In Java the only way to do this is to have a read only interface as well as a mutable one. This isn't easy to maintain and a const would be much nicer, but it's not available. You can write

interface ReadOnlyVector<T> {
    int size();
    // getter methods
    T get(int n);

    default ReadOnlyVector<T> add(ReadOnlyVector<T> v) { 
        // add two vectors and create a new one.
    }
}

interface Vector<T> extends ReadOnlyVector<T> {
    // mutating methods.
    void add(T t);
}