57

Given this code:

String test() {
    try {
        return "1";
    } finally {
        return "2";
    }
}

Do the language specifications define the return value of a call to test()? In other words: Is it always the same in every JVM?

In the Sun JVM the return value is 2, but I want to be sure, that this is not VM-dependant.

polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
Daniel Rikowski
  • 71,375
  • 57
  • 251
  • 329

7 Answers7

63

Yes, the language spec defines that "2" is the result. If a VM does it differently, it's not spec-compliant.

Most compilers will complain about it. Eclipse, for example, will claim that the return block will never be executed, but it's wrong.

It's shockingly bad practice to write code like that, don't ever do it :)

Jack Shainsky
  • 521
  • 5
  • 13
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • *don't ever do it*, apparently college professors really LOVE writing code like this, although its been 10 years since your answer – Victor Jan 12 '20 at 15:45
21

Yes, the Java Language Specification is very clear on this issue (14.20.2):

A try statement with a finally block is executed by first executing the try block. Then there is a choice:

  • If execution of the try block completes normally, [...]
  • If execution of the try block completes abruptly because of a throw of a value V, [...]
  • If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
    • If the finally block completes normally, [...]
    • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
20

The finally block will always be executed except in the following example:

String test() {
    try {
        System.exit(0);
    } finally {
        return "2";
    }
}

In this case, the JVM will stop, without executing the finally block.

So in your example, the return value will be 2.

Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
9

Yes, if you return something from the finally block, it will replace whatever you might have returned from the try or catch block.

The same is true also for exceptions. If you throw something in the finally block, that exception will replace whatever exception was thrown in the try or catch block. So be careful to never throw something in the finally block, because it may hide the original reason for a failure.

Esko Luontola
  • 73,184
  • 17
  • 117
  • 128
  • 1
    another interesting thing is that if something is returned from finally using `return` then any thrown exception is discarded. – Syed Ali Jun 27 '14 at 21:56
5

After reading the ByteCode of program, the code is as follows:

The finally block statements is inlined before the return statement of try block, so the return from the finally block executes first and the original return statement never does.

For Program:

String test() {
        try {
            System.out.println("try");
            return "1";
        } finally {
            System.out.println("finally");
            return "2";
        }
    }

It converts to:

String test()
    {
        System.out.println("try");
        String s = "1"; //temporary variable 
        System.out.println("finally");
        return "2";
        Exception exception;
        exception;
        System.out.println("finally");
        return "2";
    }

And For program: with catch block:

String test() {

        try {
            System.out.println("try");
            return "1";
        } catch (RuntimeException e) {
            System.out.println("catch");
            return "2";
        } finally {
            System.out.println("finally");
            return "3";
        }
    }

Converts to:

String test()
    {
        System.out.println("try");
        String s = "1";
        System.out.println("finally");
        return "3";
        RuntimeException e;
        e;
        System.out.println("catch");
        String s1 = "2";
        System.out.println("finally");
        return "3";
        Exception exception;
        exception;
        System.out.println("finally");
        return "3";
    }

Note: Complied using JDK 1.7 & Decompiled using Cavaj.

rhitz
  • 1,892
  • 2
  • 21
  • 26
1

You can refer the below link. I hope it will provide all details:

http://www.programmerinterview.com/index.php/java-questions/will-finally-run-after-return/

It says finally block will always executes even try or catch block has return statement. And if finally block also has return statement then this will override the return statement which is inside try or catch block and in this case any exception thrown in try/catch will be discarded (bad approach).

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
0

Above answer's is very well summarized just want to add one more point here.

private static int divide(int a , int b){
    try{
        return  a/b;
    }finally{
        System.out.println("In finally");
        return 1;
    }
}

If we pass the 1,0 then the above method will suppress the exception thrown by it and just return the result. Been said, the above code should not be used in production environment.

  private static int divide(int a , int b){
        int result = 0;
        try{
            result =   a/b;
        }finally{
            System.out.println("In finally");
            result =  1;
        }

        return result;
    }

using the return statement after the finally block will result in

Exception in thread "main" java.lang.ArithmeticException: / by zero
Arpit
  • 1,259
  • 11
  • 21