-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
None
-
8, 9, 10, 11
-
generic
-
generic
FULL PRODUCT VERSION :
All versions of Java 8 to 10ea
A DESCRIPTION OF THE PROBLEM :
JLS§9.8. states that a functional interface type may be "An intersection type (§4.9) that induces a notional functional interface". While it considers the case of combining a declared functional interface with a marker interface as "typical", it does not mandate it. In contrast, javac searches the intersection type for a declared functional interface and rejects it as target type for lambda expressions or method references when it doesn't find one.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to compile the following code
interface S {
void method1();
}
interface I1 extends S {
void method2();
}
interface I2 extends S {
@Override default void method1() {}
}
Object p = (I1&I2)() -> {};
Object q = (S&I1&I2)() -> {};
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
This could should compile without errors. It should not matter whether "(I1 & I2)" or "(S & I1 & I2)" has been used, as "S" is redundant here.
ACTUAL -
javac rejects "(I1 & I2)" as target type of a lambda expression because it doesn't find a declared functional interface in the explicitly specified types of the intersection type while it accept "(S & I1 & I2)" because it finds one.
Note that "S" is a declared functional interface in the example to demonstrate the inconsistency. It actually doesn't have to be a functional interface, i.e. it could have more than one abstract method with "I2" having default methods for all of them. Then "(I1 & I2)" should still be a notional functional interface type, as it has only one abstract method.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Bug.java:11: error: incompatible types: I1 is not a functional interface
Object p = (I1&I2)() -> {};
^
multiple non-overriding abstract methods found in interface I1
1 error
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
class Bug {
interface S {
void method1();
}
interface I1 extends S {
void method2();
}
interface I2 extends S {
@Override default void method1() {}
}
Object p = (I1&I2)() -> {};
Object q = (S&I1&I2)() -> {};
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Insert the redundant super interface, if there is a super interface that is a functional interface. Otherwise, add another interface extending all interfaces of the intersection type, to take the place of the notional functional interface, i.e. "interface NotSoNotional extends I1,I2 {}".
All versions of Java 8 to 10ea
A DESCRIPTION OF THE PROBLEM :
JLS§9.8. states that a functional interface type may be "An intersection type (§4.9) that induces a notional functional interface". While it considers the case of combining a declared functional interface with a marker interface as "typical", it does not mandate it. In contrast, javac searches the intersection type for a declared functional interface and rejects it as target type for lambda expressions or method references when it doesn't find one.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to compile the following code
interface S {
void method1();
}
interface I1 extends S {
void method2();
}
interface I2 extends S {
@Override default void method1() {}
}
Object p = (I1&I2)() -> {};
Object q = (S&I1&I2)() -> {};
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
This could should compile without errors. It should not matter whether "(I1 & I2)" or "(S & I1 & I2)" has been used, as "S" is redundant here.
ACTUAL -
javac rejects "(I1 & I2)" as target type of a lambda expression because it doesn't find a declared functional interface in the explicitly specified types of the intersection type while it accept "(S & I1 & I2)" because it finds one.
Note that "S" is a declared functional interface in the example to demonstrate the inconsistency. It actually doesn't have to be a functional interface, i.e. it could have more than one abstract method with "I2" having default methods for all of them. Then "(I1 & I2)" should still be a notional functional interface type, as it has only one abstract method.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Bug.java:11: error: incompatible types: I1 is not a functional interface
Object p = (I1&I2)() -> {};
^
multiple non-overriding abstract methods found in interface I1
1 error
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
class Bug {
interface S {
void method1();
}
interface I1 extends S {
void method2();
}
interface I2 extends S {
@Override default void method1() {}
}
Object p = (I1&I2)() -> {};
Object q = (S&I1&I2)() -> {};
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Insert the redundant super interface, if there is a super interface that is a functional interface. Otherwise, add another interface extending all interfaces of the intersection type, to take the place of the notional functional interface, i.e. "interface NotSoNotional extends I1,I2 {}".