FULL PRODUCT VERSION :
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Mac OS X 10.9.3
A DESCRIPTION OF THE PROBLEM :
Consider this snippet of java 8 code:
public class Generics {
public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
return callable.call();
}
public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
return callable.call();
}
public static void main(String[] args) throws Exception {
f(() -> 1);
g(() -> 1);
}
}
interface Callable<V> {
V call() throws Exception;
}
interface CheckedCallable1<V, E extends Exception> {
V call() throws E;
}
interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
@Override V call() throws E;
}
The lambda at the call to f compiles fine, whereas the lambda at the call to g does not compile, but rather gives this compile error:
Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
overridden method does not throw java.lang.Exception
I believe this is a compiler bug, in particular since the identical code with Exception replaced with IOException compiles fine.
Additional details are at http://stackoverflow.com/questions/24199148/lambdas-and-functional-interfaces-with-generic-throw-clauses
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the following java code:
public class Generics {
public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
return callable.call();
}
public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
return callable.call();
}
public static void main(String[] args) throws Exception {
f(() -> 1);
g(() -> 1);
}
}
interface Callable<V> {
V call() throws Exception;
}
interface CheckedCallable1<V, E extends Exception> {
V call() throws E;
}
interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
@Override V call() throws E;
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect this code to compile.
ACTUAL -
The call to g results in the following compile error:
Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
overridden method does not throw java.lang.Exception
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
overridden method does not throw java.lang.Exception
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Generics {
public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
return callable.call();
}
public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
return callable.call();
}
public static void main(String[] args) throws Exception {
f(() -> 1);
g(() -> 1);
}
}
interface Callable<V> {
V call() throws Exception;
}
interface CheckedCallable1<V, E extends Exception> {
V call() throws E;
}
interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
@Override V call() throws E;
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
1) Don't extend a functional interface without a generic throws clause in a functional interface with a generic throws clause.
or
2) Use a subclass of Exception on the functional interface without generic throws clause.