-
Bug
-
Resolution: Unresolved
-
P3
-
None
-
11
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
wsl2-ubuntu 22.04
Linux 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
javac 11.0.28
java 11.0.28 2025-07-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.28+12-LTS-279)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.28+12-LTS-279, mixed mode)
A DESCRIPTION OF THE PROBLEM :
In JDK 11, the javac compiler fails to detect this violation when abstract methods are declared in a generic class that does not have the abstract modifier. This results in successful compilation of code that should be rejected.
Notably, this issue does not occur in JDK 8, JDK 17, or JDK 21 — those versions of javac correctly report a compile-time error.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compiling following code using:
```
/path/to/jdk11/bin/javac Test.java
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The compilation should fail with a clear error message indicating that:
```
Test.java:59: error: GridEntity is not abstract and does not override abstract method getEnd() in GridEntity
class GridEntity<T extends Number> {
^
1 error
```
ACTUAL -
Javac in jdk11 complies following code successfully.
---------- BEGIN SOURCE ----------
public class Test {
public static void main(String[] strArr) {
AlignedStruct struct = new AlignedStruct();
struct.processWithLambda((int value) -> {
GridTraverser<Integer> traverser = new GridTraverser<>();
traverser.executeParallelTraversal(new GridEntity<Integer>() {});
return value * 2;
});
}
}
class Set<T extends Comparable<T>> {
private java.util.TreeSet<T> internalSet;
public Set() {
this.internalSet = new java.util.TreeSet<>();
}
public void add(T value) {
this.internalSet.add(value);
}
}
class TemplateClass<T extends Number> {
private T value;
private int parameter;
public TemplateClass(T value, int parameter) {
this.value = value;
this.parameter = parameter;
}
public T getValue() {
return value;
}
public int getParameter() {
return parameter;
}
}
interface LambdaFunction {
int apply(int value);
}
class AlignedStruct {
private int alignedValue;
public void processWithLambda(LambdaFunction lambda) {
alignedValue = lambda.apply(42);
}
}
class GridEntity<T extends Number> {
public abstract int getStart();
public abstract int getEnd();
}
class GridTraverser<T extends Number> {
public static <U extends Number> void executeParallelTraversal(GridEntity<U> entity) {
for (int i = entity.getStart(); i < entity.getEnd(); i++) {
}
}
}
---------- END SOURCE ----------
wsl2-ubuntu 22.04
Linux 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
javac 11.0.28
java 11.0.28 2025-07-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.28+12-LTS-279)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.28+12-LTS-279, mixed mode)
A DESCRIPTION OF THE PROBLEM :
In JDK 11, the javac compiler fails to detect this violation when abstract methods are declared in a generic class that does not have the abstract modifier. This results in successful compilation of code that should be rejected.
Notably, this issue does not occur in JDK 8, JDK 17, or JDK 21 — those versions of javac correctly report a compile-time error.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compiling following code using:
```
/path/to/jdk11/bin/javac Test.java
```
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The compilation should fail with a clear error message indicating that:
```
Test.java:59: error: GridEntity is not abstract and does not override abstract method getEnd() in GridEntity
class GridEntity<T extends Number> {
^
1 error
```
ACTUAL -
Javac in jdk11 complies following code successfully.
---------- BEGIN SOURCE ----------
public class Test {
public static void main(String[] strArr) {
AlignedStruct struct = new AlignedStruct();
struct.processWithLambda((int value) -> {
GridTraverser<Integer> traverser = new GridTraverser<>();
traverser.executeParallelTraversal(new GridEntity<Integer>() {});
return value * 2;
});
}
}
class Set<T extends Comparable<T>> {
private java.util.TreeSet<T> internalSet;
public Set() {
this.internalSet = new java.util.TreeSet<>();
}
public void add(T value) {
this.internalSet.add(value);
}
}
class TemplateClass<T extends Number> {
private T value;
private int parameter;
public TemplateClass(T value, int parameter) {
this.value = value;
this.parameter = parameter;
}
public T getValue() {
return value;
}
public int getParameter() {
return parameter;
}
}
interface LambdaFunction {
int apply(int value);
}
class AlignedStruct {
private int alignedValue;
public void processWithLambda(LambdaFunction lambda) {
alignedValue = lambda.apply(42);
}
}
class GridEntity<T extends Number> {
public abstract int getStart();
public abstract int getEnd();
}
class GridTraverser<T extends Number> {
public static <U extends Number> void executeParallelTraversal(GridEntity<U> entity) {
for (int i = entity.getStart(); i < entity.getEnd(); i++) {
}
}
}
---------- END SOURCE ----------