Is it possible to make an object "Read Only" to a method

18,723

Solution 1

Not strictly speaking. That is, a reference that can mutate an object can not be turned into a reference that can not mutate an object. Also, there is not way to express that a type is immutable or mutable, other than using conventions.

The only feature that ensure some form of immutability would be final fields - once written they can not be modified.

That said, there are ways to design classes so that unwanted mutation are prevented. Here are some techniques:

  • Defensive Copying. Pass a copy of the object, so that if it is mutated it doesn't break your internal invariants.

  • Use access modifiers and/or interface to expose only read-only methods. You can use access modifieres (public/private/protected), possibly combined with interface, so that only certain methods are visible to the other object. If the methods that are exposed are read-only by nature, you are safe.

  • Make your object immutable by default. Any operation on the object returns actually a copy of the object.

Also, note that the API in the SDK have sometimes methods that return an immutable version of an object, e.g. Collections.unmodifiableList. An attempt to mutate an immutable list will throw an exception. This does not enforce immutability statically (at compile-time with the static type system), but is is a cheap and effective way to enforce it dynamically (at run-time).

There has been many research proposals of Java extension to better control of aliasing, and accessibility. For instance, addition of a readonly keyword. None of them is as far as I know planned for inclusion in future version of Java. You can have a look at these pointers if you're interested:

The Checker Framework is very interesting. In the Checker Framework, look at Generic Universe Types checker, IGJ immutability checker, and Javari immutability checker. The framework works using annotations, so it is not intrusive.

Solution 2

No, not without decorating, compositing, cloning, etc.

Solution 3

There's no general mechanism for that. You'll need to write special-case code to achieve it, like writing an immutable wrapper (see Collections.unmodifiableList).

Solution 4

You could achieve a similar thing in most cases by cloning the Object as the first statement of the method, such as this...

public void readOnlyMethod(Object test){
    test = test.clone();
    // other code here
}

So if you called readOnlyMethod() and pass in any Object, a clone of the Object will be taken. The clone uses the same name as the parameter of the method, so there's no risk of accidentally changing the original Object.

Solution 5

making it implement a interface which has only read only methods (no setter methods) this gives a copy of an object (road-only copy) and returning the read only instance of interface instead of returning the instance of an object itself

Share:
18,723

Related videos on Youtube

Don Li
Author by

Don Li

Updated on June 14, 2022

Comments

  • Don Li
    Don Li almost 2 years

    If an object reference is passed to a method, is it possible to make the object "Read Only" to the method?

    • Alex Stybaev
      Alex Stybaev about 12 years
      there is an old, but still good resource: cs.uwm.edu/~boyland/papers/readonly-talk.pdf
    • Aquarius Power
      Aquarius Power over 9 years
      what about storing a reference to the object, clone it and compare from time to time if nothing changed?
  • Marko Topolnik
    Marko Topolnik about 12 years
    This requires the object to actually implement clone properly and, since this is a f*ed-up API, modern classes rarely bother with it.
  • wattostudios
    wattostudios about 12 years
    Correct. However, I would hope that most core Java classes should implement clone() properly, so this will cover most situations. Its probably about as close as you're going to get for a read-only parameter
  • Marko Topolnik
    Marko Topolnik about 12 years
    How about Collections.unmodifiableList -- that's from the core API (no cloning).
  • wattostudios
    wattostudios about 12 years
    I'm not pretending that everything is wonderful and perfect by using clone(), I'm just presenting this as a possibility that should be considered.
  • Marko Topolnik
    Marko Topolnik about 12 years
    Yes, cloning is definitely worth considering. My real point was that it is more typical today to write a custom copyOf-kind of method, or a copy-constructor, and avoid clone as the concrete mechanism to use.
  • Akki
    Akki almost 5 years
    I think if we have final field called list which is an arraylist of Custom objects and that custom object's class has setter methods in it, then we can use list.get(0).setName() or something like that to modify the final field as well, so final fields are also not strictly unmodifiable, it just means "list" field is stuck with this arrayList forever. Let me know if my understanding is not right
  • Akki
    Akki almost 5 years
    Even returning a clone of the object is not foolproof, if we think about it