Question

I have seen a couple of such tricky pieces of code while i prepare for a Java certification.

The return value at the end here is : 10, but finally is called and it modifies the returnval to 20.

Can someone explain why this is so ? is it because the catch has a different scope of the returnval ? or am i missing something here.

class MultipleReturn {
int getInt() {
int returnVal = 10;
try {
     String[] students = {"Harry", "Paul"};
     System.out.println(students[5]);
    }
catch (Exception e) {
    System.out.println("About to return :" + returnVal);
    return returnVal;
    }
finally {
    returnVal += 10;
    System.out.println("Return value is now :" + returnVal);
    }
return returnVal;
}

public static void main(String args[]) {
       MultipleReturn var = new MultipleReturn();
       System.out.println("In Main:" + var.getInt());
      }
}

Another follow up piece of code is :

class MultipleReturn {
  StringBuilder getStringBuilder() {
  StringBuilder returnVal = new StringBuilder("10");
  try {
      String[] students = {"Harry", "Paul"};
      System.out.println(students[5]);
  }
  catch (Exception e) {
      System.out.println("About to return :" + returnVal);
      return returnVal;
  }
  finally {
     returnVal.append("10");
     System.out.println("Return value is now :" + returnVal);
  }
  return returnVal;
  }

  public static void main(String args[]) {
    MultipleReturn var = new MultipleReturn();
    System.out.println("In Main:" + var.getStringBuilder());
  }
}

here the output is 1010 which makes sense as the finally modifies the returnval and it gets persisted.

Any explanation will be helpful.

i do understand this is poorly written code and nobody in the right mind should be writing anything like this.

Was it helpful?

Solution

In the first example finally doesn't change anything because 10 is already marked as a value to return inside catch statement. If you add return to the finally block or remove return from catch and leave only the last return statement than you will get value 20. The most important thing is that you return only value not a reference here.

On the other hand in the second example StringBuilder is mutable and returnVal is a reference to the object. Than returnVal with value "10" is marked as a value to return, but before you print value of returnVal inside main method finally block is executed and it changes value of the returnVal from "10" to "1010". Than if you print returnVal inside main method you will get the latest value of this object which is "1010". It works like that because getStringBuilder returns reference of StringBuilder which is mutable.

OTHER TIPS

There's a lot going on here, but I think what it boils down to is that in the getStringBuilder version the returnVal object is mutable and the same object is mutated in the finally clause returning "1010" as you observed. On the other hand, a different value is returned when you add 10 to the integer in your finally clause that has a different address in memory than the value being returned.

Try running the following code to maybe better illustrate.

class MultipleReturn {
  int getInt() {
    int returnVal = 10;

    System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
    try {
      String[] students = { "Harry", "Paul" };
      System.out.println(students[5]);
    } catch (Exception e) {
      System.out.println("About to return :" + returnVal);
      System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
      return returnVal;
    } finally {
      returnVal += 10;
      System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
      System.out.println("Return value is now :" + returnVal);
    }
    return returnVal;
  }

  StringBuilder getStringBuilder() {
    StringBuilder returnVal = new StringBuilder("10");

    System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
    try {
      String[] students = { "Harry", "Paul" };
      System.out.println(students[5]);
    } catch (Exception e) {
      System.out.println("About to return :" + returnVal);
      System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
      return returnVal;
    } finally {
      returnVal.append("10");
      System.out.println("Return value is now :" + returnVal);
      System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
    }
    return returnVal;
  }


  static class MutableInteger {
    public int val;

    @Override
    public String toString() {
      return Integer.toString(val);
    }
  }


  MutableInteger getMutableInt() {
    MutableInteger returnVal = new MutableInteger();
    returnVal.val = 10;
    System.out.println("Identiy hash of returnVal: " + System.identityHashCode(returnVal));
    System.out.println(System.identityHashCode(returnVal));
    try {
      String[] students = { "Harry", "Paul" };
      System.out.println(students[5]);
    } catch (Exception e) {
      System.out.println("Identiy hash of returnVal in catch block: " + System.identityHashCode(returnVal));
      System.out.println("About to return :" + returnVal);
      return returnVal;
    } finally {
      returnVal.val += 10;
      System.out.println("Identiy hash of returnVal in finally: " + System.identityHashCode(returnVal));
      System.out.println("Return value is now :" + returnVal);
    }
    return returnVal;
  }  

  public static void main(String args[]) {
    MultipleReturn var = new MultipleReturn();
    System.out.println("In Main:" + var.getInt());
    System.out.println();
    System.out.println("In Main:" + var.getStringBuilder());
    System.out.println();
    System.out.println(var.getMutableInt());
  }
}

Results:

Identiy hash of returnVal: 1152321476 About to return :10 Identiy hash of returnVal in catch block: 1152321476 Identiy hash of returnVal in finally: 2116610996 Return value is now :20 In Main:10

Identiy hash of returnVal: 814397217 About to return :10 Identiy hash of returnVal in catch block: 814397217 Return value is now :1010 Identiy hash of returnVal in finally: 814397217 In Main:1010

Identiy hash of returnVal: 1660743788 1660743788 Identiy hash of returnVal in catch block: 1660743788 About to return :10 Identiy hash of returnVal in finally: 1660743788 Return value is now :20 20

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top