20

I've seen some code as below in some example BlackBerry Java classes:

try
{
    // stuff that will throw an exception
}
catch(final Exception e)
{
    // deal with it
}

I presume the final is for performance. As per the title, since there's rarely (ever?) any reason to modify an Exception that's already been thrown, should they always be final?

If so, isn't this something that could be done by the compiler? Or is it done by the compiler and adding the final manually has no impact at all?

Matt
  • 9,068
  • 12
  • 64
  • 84
  • 2
    Related: http://stackoverflow.com/questions/6889270/java-7-precise-rethrow-with-a-final-exception – assylias Aug 21 '12 at 09:21
  • 3
    There is neither any particular reason to use, nor not to use `final`. Performance is out of the question. – Marko Topolnik Aug 21 '12 at 09:23
  • Full details on Java 7 exception variable semantics: http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html – Marko Topolnik Aug 21 '12 at 09:27
  • The only thing I could think of is that it is to avoid accidental reassignment of exception since you will loose all stack trace in such case. – Amit Deshpande Aug 21 '12 at 09:30

5 Answers5

17

The Java Language Specification 11.2.2 makes a difference between final and not final exceptions:

A throw statement (§14.18) whose thrown expression has static type E and is not a final or effectively final exception parameter can throw E or any exception class that the thrown expression can throw.
[...]
A throw statement whose thrown expression is a final or effectively final exception parameter of a catch clause C can throw an exception class E iff:

  • E is an exception class that the try block of the try statement which declares C can throw; and
  • E is assignment compatible with any of C's catchable exception classes; and
  • E is not assignment compatible with any of the catchable exception classes of the catch clauses declared to the left of C in the same try statement.

Interestingly, JLS 14.20 also says:

In a uni-catch clause, an exception parameter that is not declared final (implicitly or explicitly) is considered effectively final if it never occurs within its scope as the left-hand operand of an assignment operator.

In other words, if you don't reassign the e of your catch statement (like e = new SomeOtherException();), it is implicitly declared final.

So I can only conclude that it does not make a difference, unless the exception is modified in the catch block and the only example I can come up with is:

public void method1() throws IOException {
    try {
        throw new IOException();
    } catch (Exception e) { // e is not modified in catch => implicitly final
        throw e; //compiles OK
    }
}

//it works because method1 is semantically equivalent to method2:
public void method2() throws IOException {
    try {
        throw new IOException();
    } catch (final Exception e) {
        throw e;
    }
}

public void method3() throws IOException {
    try {
        throw new IOException("1");
    } catch (Exception e) {
        e = new IOException("2"); //e modified: not implicitly final any more
        throw e; //does not compile
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    Trying to understand what that means ;-) – assylias Aug 21 '12 at 09:33
  • Can you provide an example of how using `final` makes a difference? e.g. with `final` you can do X, but with out `final` you cannot. – Peter Lawrey Aug 21 '12 at 09:36
  • 2
    The day they introduce syntactic sugar to automagically wrap checked exceptions into a `RuntimeException`, they'll get my attention :) – Marko Topolnik Aug 21 '12 at 10:16
  • I cannot compile none of these methods from IntelliJ. What am I doing wrong? I get message "unreported exception java.lang.Exception; must be caught or declared to be thrown". – Roman Aug 21 '12 at 12:14
  • @Roman Are you using a Java 7 compiler (it would not compile with Java 6 or earlier)? – assylias Aug 21 '12 at 12:37
  • With the risc of stating the obvious: So I assume the point is that by changing the caught exception it is not longer (implicitly) final and the compiler can therefore no longer know whether or not the thrown Exception e is indeed an IOException (as defined in the signature's 'throws' part), or some other subclass of Exception. – Hervian May 17 '16 at 11:02
2

I believe final is useful when the code which could use it is too long to easily read and understand. e.g. I would make fields final where possible to ensure they are assigned correctly in constructors and not modified anywhere in the class.

Using final for a catch clause is unlikely to help much as a) the value is guaranteed to be set b) the code using it should be short, c) its very rare to modify it anyway.

There is nothing stopping you from doing it however.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I do not get your point of `final` being useful when code is "too long to easily read and understand". can you please explain a bit? – Geek Jul 21 '14 at 14:49
  • A bit late to the party, but the point is that final variables can only be assigned once in each possible execution path, which is very useful if the code branches too much, or if the method is too long (you can assume that the value is not going to change). Shameless plug: I wrote a bit about it [here](https://glastra.net/final-keyword-considered-awesome/) (with some added extreme opinions that you may or may not disagree with). – Gerardo Lastra Sep 01 '16 at 14:19
0

I'm not sure it's about performance, but more about convention. If you're using Eclipse, try to set a formatter that add the final keyword wherever it's possible, and reformat your source code with that formatter.

sp00m
  • 47,968
  • 31
  • 142
  • 252
-1

I doubt final would really give any performance benefit because the exception instance is block local (Here is a really good answer explaining it https://stackoverflow.com/a/306966/492561).

So It merely serves as a explicit marker that says I will not modify.

Some times you may need to modify the exception to throw it back, may be edit the message to make it more clear at higher levels.

Essentially I would say that its a matter of preference, Some may like it others may not.

Community
  • 1
  • 1
Gautam
  • 7,868
  • 12
  • 64
  • 105
  • Exceptions don't let you modify the message (if you refer to the one used in the Throwable et al ctor), but even if they would, the exception could be final... `final` prevents reference reassignment, not internal state modification. Also, "modify to throw back"... You could (and should) throw a new instance. – Gerardo Lastra Sep 01 '16 at 14:29
-1

I've seen a couple of projects where everything what is not modified must be final (e.g. parameters, fields, local vars etc).

There's also a correspondent style check in PMD code analyzer, which verifies that everything what possible is declared as final.

Roman
  • 64,384
  • 92
  • 238
  • 332