Summary
-------
Produce an error/warning for method that override/implement a preview method.
Problem
-------
Consider a method declared as a preview method in an interface I or a class C (using the unexported JDK-private annotation `@PreviewFeature`). A good example in Java 19 is the preview method `ofVirtual` declared in class `Thread`.
A class D that `implements I` or `extends C` and directly implements I's method or overrides C's method does not receive an error or warning at compile time. The lack of error or warning is a problem, because D is clearly dependent on the preview API in I or C.
Note that the interface I or the class C is not itself a preview API. (For example, in Java 19, the class `Thread` is not a preview API, despite declaring preview methods like `ofVirtual`.)
If D is an abstract class, then it can `implements I` or `extends C` _without_ directly implementing I's method or overriding C's method. In this case, no error or warning is needed. The first concrete subclass of D is on the hook to directly implement or override the preview method in I or C, and that concrete subclass is the artifact which needs an error or warning.
Once a concrete class has directly implemented or overridden the preview method in I or C (and received an error or warning for doing so), then subclasses of that concrete class do not need any kind of error or warning relating to the preview method in I or C. That is, the concrete class forms a barrier between the part of the class hierarchy that depends on the preview method, and the part of the class hierarchy that doesn't.
Solution
--------
javac will be fixed to produce errors/warnings for methods that directly implement or override a preview method.
Consider a (currently non-existing) instance preview method in Thread:
package java.lang;
public class Thread {
@PreviewFeature(feature=TEST)
public void demo() {}
}
Now, consider the following examples:
package java.util;
public class Test1 extends Thread {
@Override
public void demo() {} //no warning or error, as it is in the same module
}
package test; //in a user module "m"
public class Test2 extends Thread {
} //no warning or error, as the "demo" method is not overridden
package test;
public class Test3 extends Thread {
@Override
public void demo() {} //a preview error when compiling without --enable-preview, a preview warning when compiling with --enable-preview, subject to further @SuppressWarnings and/or -Xlint:+/-preview
}
package test;
public class Test4 extends Test3 {
@Override
public void demo() {} //no warning or error, as the appropriate diagnostics was already given in the super class
}
package test;
public class Test5 extends Test2 {
@Override
public void demo() {} //a preview error when compiling without --enable-preview, a preview warning when compiling with --enable-preview, subject to further @SuppressWarnings and/or -Xlint:+/-preview
}
If the preview method would be a reflective preview method:
package java.lang;
public class Thread {
@PreviewFeature(feature=TEST, reflective=true)
public void demo() {}
}
then the Test3 and Test5 cases would be altered:
package test;
public class Test3 extends Thread {
@Override
public void demo() {} //a preview warning when compiling with or without --enable-preview, subject to further @SuppressWarnings and/or -Xlint:+/-preview
}
package test;
public class Test5 extends Test2 {
@Override
public void demo() {} //a preview warning when compiling with or without --enable-preview, subject to further @SuppressWarnings and/or -Xlint:+/-preview
}
If the preview method was static (reflective or not):
package java.lang;
public class Thread {
@PreviewFeature(feature=TEST)
public static void demo() {}
}
there would be no preview-related errors or warnings for any subclasses. (Although there may be traditional "instance method cannot override static" errors.)
Specification
-------------
(Recall from JLS 1.5 that: "Some preview APIs are described as _reflective_ by the Java SE Platform Specification, principally in the java.lang.reflect, java.lang.invoke, and javax.lang.model packages. ... All preview APIs not described as reflective in the Java SE Platform Specification are _normal_.)
A method that directly implements or overrides a preview method outside of the module that declares the method will get either:
- a non-suppressible compile-time error (for normal preview methods when preview mode is disabled), or
- a suppressible preview warning (for reflective preview methods when preview mode is disabled, or normal preview methods when preview mode is enabled).