3

I have to implement an interface method that has the signature like:

public int runMethod(final int key, Reference <String> result);

I have to update the value of result parameter before method returns. For example if the value of result was ABC when the method was invoked, I need to modify it as DEF and return to caller. Can somebody suggest how do I achieve it?

Shashi
  • 14,980
  • 2
  • 33
  • 52

3 Answers3

14

You can't modify the variable that you passed to the method. For example:

public int runMethod(final int key, Reference <String> result) {
    result = null; // Only changed the method's version of the variable, and not the variable that was passed to the method
}
...
Reference<String> ref = ...
runMethod(0, ref);
// ref is still what you originally assigned it to

However, you can modify the fields and call the methods of the object you pass.

public int runMethod(final int key, Reference <String> result) {
    result.someField = ...; // Here we are changing the object, which is the same object as what was passed to the method.
}
...
Reference<String> ref = ...
runMethod(0, ref);
// ref.someField has now been changed

An alternative would be to change the method's return type to Reference<String> and return the updated value.

public Reference<String> runMethod(final int key, Reference <String> result) {
    return ...;
}
...
Reference<String> ref = ...
ref = runMethod(0, ref);
// ref is now whatever you returned from the method
SamTebbs33
  • 5,507
  • 3
  • 22
  • 44
  • More generally, Java always passes by value, either for primitive and refenrene type, more here : https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html – La VloZ Merrill May 29 '16 at 02:15
  • 4
    This correctly explains argument passing, but neither the `Reference` interface nor any of the three implementation classes in the standard library provide a mechanism to change what object an instance refers to. They are not intended for the kind of use the OP seems to be trying to put them to. – John Bollinger May 29 '16 at 02:16
  • 2
    @JohnBollinger Ah, I didn't realise that there was a `Reference`type in the standard library and assumed it was a third-party type. – SamTebbs33 May 29 '16 at 02:17
  • He can't change the return type to a type which is not incompatible with the implemented one. – La VloZ Merrill May 29 '16 at 02:27
  • Well, thank you all. I also thought the 'Reference' was from java.lang.Reference. But on further investigation found that it's from a third party and has an assign method. – Shashi May 29 '16 at 03:04
  • @LaVloZMerrill Please check my edit, I simply forgot to change the method's return type in the example code. It was quite late at night. – SamTebbs33 May 29 '16 at 11:06
  • @SamTebbs33 unfortunately he coudn't change the return type from `int` to `Reference` because `Reference` type isn't incompatible with 'int`, see this : http://stackoverflow.com/questions/14694852/can-overridden-methods-differ-in-return-type – La VloZ Merrill May 29 '16 at 13:55
  • @LaVloZMerrill Well obviously it isn't. If the return type *can* be changed then it is a way of achieving what the OP wanted. – SamTebbs33 May 29 '16 at 16:46
  • @SamTebbs33 we can change return type for overriden methods to only compatible type and `Reference` isn't compatible with `int` – La VloZ Merrill May 29 '16 at 18:00
  • @SamTebbs33 the OP said that he must implement an interface which contains that method ;) – La VloZ Merrill May 29 '16 at 20:48
  • @LaVloZMerrill Yes but if you change the return type of the interface's method, then there won't be a problem! – SamTebbs33 May 29 '16 at 23:27
  • @SamTebbs33 of course isn't a problem, but usually you don't change the interface, cause if there's many classes which implement it, it would be a pain to do that, another thing, what if the interface is in a third party library?!!! – La VloZ Merrill May 30 '16 at 08:34
  • 1
    @LaVloZMerrill That's why I first said if you *can* change the return type, then it is an alternative, if not then don't do it, as I have already said..... – SamTebbs33 May 30 '16 at 10:42
3

If you really want to pass as reference, here is a tricky way by wrapping it in an array:

class TestRef{
  static void func(int[] arr){arr[0] = -arr[0];}
  public static void main(String[] args){
    int[] arrI = new int[1];
    arrI[0] = 250;

    System.out.println(arrI[0]); // 250
    func(arrI);
    System.out.println(arrI[0]); // -250
  }
}
-2

In java objects are in effect passed by reference. That is, parameter 'result' within runMethod appears to be exactly the same object as in the caller, not a copy. So, by updating the contents of Reference parameter of runMethod you will be achieving the goal you have described.

However, 'result' itself is not actually a pointer to the caller's passed variable so it is not possible to overwrite the object itself, only update it's contents.

Richard Guy
  • 470
  • 4
  • 12
  • 4
    In Java, all arguments are passed by *value*. This includes references. In runMethod, `result` is a *copy* of the `Reference` reference that was provided as an argument. The two are independent references to the same object. – John Bollinger May 29 '16 at 02:10
  • It would have been straight forward if Java passed parameters by Reference. But it's not. – Shashi May 29 '16 at 02:14
  • OK, according to the Java spec you are correct. But, can you explain this in a simple way which does not just add more confusion to this simple question? The behaviour is that of pass by reference. – Richard Guy May 29 '16 at 02:14
  • Java is *pass-by-reference* (for non-primitive types) since the same object reference is passed to the method, the method parameters just don't have any link to the actual variables that were passed to the method. Only the contents of the object can be changed, and not the variable being passed itself. – SamTebbs33 May 29 '16 at 02:16
  • 1
    This is basically a semantic argument and of no help to the question. – Richard Guy May 29 '16 at 02:18
  • Yeah I want to change the contents – Shashi May 29 '16 at 02:19
  • I do see the distinction, please see amended answer. Basically, calling result.updateSomething() or result.publicProperty = "something" will work as you want but result = null; will not cause the callers variable to become null as the parameter received by runMethod is not a true pointer. – Richard Guy May 29 '16 at 02:30