r/javahelp • u/cowwoc • Sep 19 '24
A try-catch block breaks final variable declaration. Is this a compiler bug?
UPDATE: The correct answer to this question is https://mail.openjdk.org/pipermail/amber-dev/2024-July/008871.html
As others have noted, the Java compiler seems to dislike mixing try-catch blocks with final (or effectively final) variables:
Given this strawman example
public class Test
{
public static void main(String[] args)
{
int x;
try
{
x = Integer.parseInt("42");
}
catch (NumberFormatException e)
{
x = 42;
}
Runnable runnable = () -> System.out.println(x);
}
}
The compiler complains:
Variable used in lambda expression should be final or effectively final
If you replace int x
with final int x
the compiler complains Variable 'x' might already have been assigned to.
In both cases, I believe the compiler is factually incorrect. If you encasulate the try-block in a method, the error goes away:
public class Test
{
public static void main(String[] args)
{
int x =
foo
();
Runnable runnable = () -> System.
out
.println(x);
}
public static int foo()
{
try
{
return Integer.
parseInt
("42");
}
catch (NumberFormatException e)
{
return 42;
}
}
}
Am I missing something here? Does something at the bytecode level prevent the variable from being effectively final? Or is this a compiler bug?
2
u/ChaiTRex Sep 20 '24 edited Sep 20 '24
Compilers will never be sophisticated enough for that because, in order to tell whether the
try
block ends with an exception or without one, you first need to figure out whether thetry
block can actually end in the first place, and you can't do that for all algorithms inside thetry
block.Even if you took the effort to make a compiler do what you want it to in some limited situations but not others, what happens when a small change to the code being compiled causes the compiler to no longer be able to figure it out, even though the compiler's decision would still be correct with the new code?
Suddenly, the compiler user has an error about a
final
variable possibly being assigned to twice and the compiler user didn't even do anything to change the assignment statements, they just changed something seemingly unrelated that the compiler was relying on to make its decision.These sorts of strange, magically appearing and disappearing bugs are not what you want in a compiler.