4

I have a method that take multiple arguments, some of these arguments will be changed inside the method. Some are used as read only. The client (other parts of the code that call such a method) provide object instances as arguments.

What constructs of the java language are available that let me declare that an argument shouldn't or won't or can't be mutated inside the method. Constrcuts like annotations or keywords, that tell the client that the method won't change the objects instances used as arguments in the method call. Also constructs that would generate compilation errors or warning in case I (as an implementor of such a method) try to mutate the object accidently inside the method implementation.

I know about the keyword final but this is only to make sure that a reference is not updated.

Immutability is not a solution, as in other methods (or elsewhere in my application) I want to have instances of the type to be mutable, only within this method call, I want to give a "promise" to the client, that I won't change his instance provided as an argument.

Deep copying or cloning the argument or letting the client(caller) do such a thing is not necessary, as it is not part of the logic of the method to change the instance anyways. I just want to make to know if the language will help double check this won't happen.

StaticBug
  • 557
  • 5
  • 15
  • you could make deep copy and pass that. – John Nov 18 '15 at 14:35
  • One dirty way is to use the [StackTraceElement](http://stackoverflow.com/questions/421280/how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection) to extract last called method / class. You can throw an exception (`UnsupportedOperation`?) if call to this method (setter method) has been done from an *unacceptable context*. I actually don't think this is a good idea :P – TheLostMind Nov 18 '15 at 14:47

3 Answers3

4

There's no way to define an argument read-only (only what you already mentioned). However, you can use the builder pattern to build the passed object so that the built object will only have getter methods, thus it won't have setter methods making it effectively immutable (note that reflection still can be used to modify its fields).

Gergely Kőrössy
  • 5,620
  • 3
  • 28
  • 44
3

You are looking for immutability. final ensures that the reference cannot be updated, but mutable fields can still be changed. By making instances of a class immutable, you can ensure that value of an instance never changes.

Check strategy for defining immutable Objects

If you don't want to make your instances immutable, you can still give the client a guarantee that the Object presented to them won't change by passing a defensive copy / deep copied instance.

TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • 1
    I think OP is aware of that. – Mena Nov 18 '15 at 14:34
  • @Mena - I thought that OP only knew about `final` fields and not about *immutable instances*. Also, I don't see any good way of actually doing this apart from using defensive copies or making the object immutable. – TheLostMind Nov 18 '15 at 14:37
  • immutability is not a solution, as in other methods (or elsewhere in my application) I want to have instances of the type to be mutable, only within this method call, I wan't to give a "promise" to the client, that I won't change his instance provided as an argument – StaticBug Nov 18 '15 at 14:37
  • @StaticBug - Then use defensive copies of your instances like Mena mentions – TheLostMind Nov 18 '15 at 14:38
3

There's no pure java solution for you there.

As you mentioned, the final keyword will only ensure no new value can be assigned to that reference.

One precaution you can use is to clone, or wrap around your mutable arguments depending on the case.

There are some (cumbersome) techniques available to deep-clone collections and maps (see here and here for quick examples within SO).

Ultimately, a well-presented and thorough javadoc can provide the appropriate level of documentation here.

Community
  • 1
  • 1
Mena
  • 47,782
  • 11
  • 87
  • 106