0
public class TestException extends except2 {

    public static void main(String[] args)throws Exception  {
       try {
            try {
                throw new TestException();
            }
            catch (final TestException e){         
            }
            throw new except2();
        }
        catch (TestException a){
        }
        catch (Exception e){
            throw e;
        }
    }

    public TestException(){
    }
}

class except2 extends Exception{
}

Hi all,

my JDK version is 8u45 which is latest one now.

I'm wondering that is "precise rethrow with a final exception" still working in SE 8?

As the code, if I take the "throws Exception" off it'll be compilation error, but it should be able to be ignored according to "precise rethrow with a final exception" function of SE7.

Another question is that we all know if there's an exception happened in the nested try box, we should still throw it out to outer catch box to avoid compilation error, I originally figured that we only need to throw an exception of any types & it'll do, so is my test result, I think it's to let compiler know that there's an exception in try box & catch box got it, too.

but if I alter it like the following code:

public class TestException extends except2 {
    public static void main(String[] args)throws Exception  {
       try {
            try {
                throw new ArithmeticException();
            } catch (final TestException e){
                throw e;
            } 
        } catch (TestException a){
        } catch (Exception e){
            throw e;
        }
    }
}

the (final TestException e) part will be compilation error with the message:

"the Exception "com.xxx.TestException" is never thrown in the corresponding try block",

and I'm confused because if nested catch block can't handle the exception, it shall goes to outer.

Then if I throw an ArithmeticException in the end of outer try block like this:

try {
    try {
        throw new TestException();
    }
    catch (final TestException e){
        System.out.println("d");
    }

    throw new ArithmeticException();
}
catch (TestException a){
}
catch (Exception e){
    throw e;
}

Same error to the outer catch box catch (TestException a){}

Why is that?

it should be caught by (Exception e) block.

If I can't throw different types of exception from the first exception of nested try block, why could I throw except2 in the first paragraph of code?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724

2 Answers2

2

This is Oracles example for the feature, and it still works with Java 8:

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName)
   throws FirstExceptio, SecondException // Since J7 no "Exception" needed
{
  try {
    if (exceptionName.equals("First")) {
      throw new FirstException();
    } else {
      throw new SecondException();
    }
  } catch (Exception e) {
    throw e; // effective final (i.e. not assigned)
  }
}

This is described in the second half of this Oracle document. Your examples are all not really related to it. Especially not the one where you have a more specific and a general catch. This is explicitly mentioned in the document as not working.

Your first block would work if you use except2 (I renamed it to BaseException) which is the more specific one like this:

public class TestException extends BaseException {

    public static void main(String[] args) {
       try {
            try {
                throw new TestException();
            }
            catch (final BaseException e){
              throw e; // this is defined as BaseEx, will fail on Java 6
            }
        }
        catch (TestException a){ // this knows that no BaseEx is expected
        }
    }

    public TestException(){
    }
}

class BaseException extends Exception { }

As you can see, the main() method does not need to throw Exception anymore since the second catch block was sufficient.

eckes
  • 10,103
  • 1
  • 59
  • 71
  • Sry mate don't really get what u meant, I think my code wasn't violate the rules described in the docs.can u plz explain more? Appreciate! – Kiah Starck Jun 11 '15 at 10:40
  • I was just refering to the "There are no other preceding catch blocks that can handle it" which would be the case for `catch (TestException e1) { } catch (Exception e2) {}` – eckes Jun 12 '15 at 02:22
  • sry which code block r u currently mean? 1,2 or 3?well in first code the nested try-catch block finally throws `except2`, it can't be handled by `catch (TestException a)` so it's caught by `catch (Exception e)` but according to the feature of precise rethrow we shall be able to ignore noting it in `throws` after method signature but it's not in my result that's my question point. – Kiah Starck Jun 12 '15 at 17:17
  • The first clode block, I added a variant to my answer which actually does use/work with precise rethrow. – eckes Jun 12 '15 at 17:49
  • sry mate..don't know which part u meant@@ – Kiah Starck Jun 14 '15 at 11:57
1

Your first piece of code can be shortened to

class TestException extends except2 throws Exception {
    public static void main(String[] args) {
        try {
            throw new except2(); // this
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }

    public TestException() {
    }
}

class except2 extends Exception {
}

You're throwing an except2. A TestException is an except2, but an except2 is not necessarily a TestException. The first catch block cannot handle the except2 exception. So the second one must. Since it further throws that exception, and that exception is necessarily checked, you need to have a throws clause.

Your second piece of code

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            try {
                throw new ArithmeticException();
            } catch (final TestException e) { // nothing above throws a TestException
                throw e;
            }
        } catch (TestException a) {
        }
        catch (Exception e) {

            throw e;
        }
    }
}

Is trying to catch a TestException in the nested try block. But since TestException is a checked exception, the compiler can and does check if it can be thrown in that block. In your case, it can't. So it complains that's it useless to try and catch it.

Finally, in your last snippet

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            try {
                throw new TestException();
            } catch (final TestException e) {
                System.out.println("d");
            }
            throw new ArithmeticException();
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }
}

You're throwing and catching a TestException in the nested try-catch statement. So you can reduce the code to

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            throw new ArithmeticException();
        } catch (TestException a) {
        } catch (Exception e) {
            throw e;
        }
    }
}

Which has the same issue as your second piece of code. There is no code path there that can throw a TestException.


Regarding comments, and to simplify the second snippet, the error reduces to

class TestException extends except2 {
    public static void main(String[] args) throws Exception {
        try {
            throw new ArithmeticException();
        } catch (final TestException e) { // nothing above throws a TestException
            throw e;
        }
    }
}

You have a catch(TestException) but nothing throws a TestException, so it's useless code which the compiler rejects.


From comments, this is the problem with your cases 2 and 3

// ignore everything around this
try {
    // nothing in this block 
    // can throw a TestException

    throw new ArithmeticException();

// this whole catch block is useless code
// Test Exception can never be thrown
} catch (final TestException e){ 
    throw e;
} 
// ignore everything around this
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Sry bro but the idea of the feature "precise rethrow with a final exception " is that compiler will automatically verify the actual type of ur rethrown exception, so u don't have to add the super exception's type of the catch block which has caught it, in this case is "Exception"?thx! And the second part, yes the ArithmeticException can be caught by the nested TestException try block but it should be left to the other catch block for continuously matching rite? And then probs still happens. – Kiah Starck Jun 11 '15 at 10:52
  • Then about the third part, we don't need to be definitely rethrowing obj in each catch block unless u have noted it in throws of the method signature rite? In this case why TestException catch block needs rethrow? – Kiah Starck Jun 11 '15 at 11:00
  • @kiah In the first sample, you throw a `except2`, which is a checked exception. **This cannot be caught by the `catch(TestException)`**. It must therefore be caught by the `catch(Exception)`. Since `except2` is a checked exception and that is the only exception that the compiler knows about, you must handle the fact this exception is rethrown, either with another enclosing `try-catch` statement or with a `throws` declaration at the method level. – Sotirios Delimanolis Jun 11 '15 at 14:47
  • @KiahStarck A `catch(TestException)` **cannot** catch an `ArithmeticException`. But that's not the problem. The problem is that the compiler knows that **nothing in that second snippet** can thrown a `TestException` that would be caught by that nested `catch(TestException)`**. It therefore rejects the code with an error. – Sotirios Delimanolis Jun 11 '15 at 14:49
  • > **nothing in that second snippet can thrown a TestException that would >be caught by that nested catch(TestException)** I think u meant the second code which has nested `catch(TestException)` My awareness of it is that the nested try did throw the `TestException`, and the nested catch block did caught, but we still need to throw an exception for the enclosing catch blocks otherwise it'll be compilation error, but if we throw `except2`, it works, if throws `ArithmeticException` it'll be error, but it should be both passing the compilation, that's where my question is. Appreciate! – Kiah Starck Jun 11 '15 at 15:37
  • @KiahStarck Can you link to what you read so I can understand where your confusion comes from? You can omit the `throws` declaration if the compiler can determine that an exception rethrown within a `catch(Exception)` block [isn't a checked exception](http://stackoverflow.com/questions/6115896/java-checked-vs-unchecked-exception-explanation). – Sotirios Delimanolis Jun 11 '15 at 15:42
  • **you must handle the fact this exception is rethrown, either with another enclosing try-catch statement or with a throws declaration at the method level.** Hi man, thx a lot for ur replying first! I'm fully aware of that, but the question is that the feature "precise rethrow"of SE7 & later allows us to skip noting `throws Exception` bcuz the compiler will automatically record the real type of the obj caught by `catch(Exception e)`, is my thought to the feature rite? – Kiah Starck Jun 11 '15 at 15:42
  • @KiahStarck See my edit for your second snippet. It's much simpler than what you are discussing. – Sotirios Delimanolis Jun 11 '15 at 15:45
  • sry I read it from my book written in chinese @@ http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html plz see the part of *Rethrowing Exceptions with More Inclusive Type Checking* – Kiah Starck Jun 11 '15 at 16:23
  • @KiahStarck Right. So none of that applies to any of the examples you have here. – Sotirios Delimanolis Jun 11 '15 at 16:55
  • @@ it says that we can ignore noting the `Exception` type in the `throws` of method signature for `catch(Exception e)` rite? So my first code was simply asking why can't I ignore `throws catch(Exception e)` in the case? 2 & 3 code was just asking that `ArithmeticException` should be able to be caught by `catch(Exception e)` as well, but why compilation error for `catch(TestException e)? it should just be skipped bcuz it can't handle the thrown exception which is `ArithmeticException`. – Kiah Starck Jun 12 '15 at 17:24
  • @KiahStarck See my edit concerning the `ArithmeticException`. You have a block of code that only contains `throw new ArithmeticException();`. Nothing in that block of code can throw a `TestException`, so there is no reason to have a `catch` block for it. – Sotirios Delimanolis Jun 12 '15 at 17:46
  • @KiahStarck What the article you linked to says is that the compiler is now smart enough to know what exceptions can possibly be re-thrown from within a `catch(Exception)`. None of it applies to your examples. – Sotirios Delimanolis Jun 12 '15 at 17:48
  • @ Sotirios Delimanolis WOW I think I was misunderstood by my book, the feature actually means u can add the actually type of the rethrown obj in the `throws`, not the catch block's type, doesn't mean that u can skipped both the actual type & catch type. Sry for bothering mate! but my questions of code 2&3 still stand, why the error of **"the Exception "com.xxx.TestException" is never thrown in the corresponding try block"** when I rethrow `ArithmeticException`? – Kiah Starck Jun 12 '15 at 18:27
  • @KiahStarck See the last part of my answer. The problem **is not** with `ArithmeticException`. The problem is with the `catch (TestException)`. How can you catch something that is never thrown? – Sotirios Delimanolis Jun 12 '15 at 18:31
  • Sry mate..still don't understand.. In my awareness, the try-catch expression works as the following steps: `ArithmeticException` is thrown > `Catch(TestException)` can't handle it, so skip this catch block > goes to `catch(Exception)` which can catch it > execute the statements of `catch(Exception)` in try-catch feature, it will automatically check all catch blocks & see which one that can match the thrown exception of try blocks, if it doesn't match then skip it. In this case why'd `catch(TestException)` definitely need to catch something otherwise compilation error? – Kiah Starck Jun 14 '15 at 11:54
  • @kiah See the fifth bolded paragraph [here]( https://docs.oracle.com/javase/specs/jls/se8/html/jls-11.html#jls-11.2.3). A `try` statement has the form `try { some-statements } catch { some-exceptions }`. If `some-statements` aren't declared to throw any of the checked exceptions declared in the `catch`'s `some-exceptions`, then that is a compile time error, because the `catch` block would be useless, a type of unreachable code. – Sotirios Delimanolis Jun 14 '15 at 12:29
  • hi man, thx for help so much!!! I responded by a new answer form, hoping that can get ur feedback again!! @Sotirios Delimanolis – Kiah Starck Jul 25 '15 at 12:27
  • Thank u so much for patient response!!! And also sry for my late reply caused by some other researches.I've added my further question as a new answer, plz help me again if possible!!THX!! – Kiah Starck Jul 27 '15 at 10:16