Summary
-------
Add `implSpec` tags `AccessibleObject`, deprecate its constructor, and seal `Executable`.
Problem
-------
Conceptually, `AccessibleObject` is a sealed class with a protected constructor stating
> Constructor: only used by the Java Virtual Machine.
Several of the methods defined on `AccessibleObject` unconditionally throw exceptions as they are meant to be overridden in all subclasses.
However, it is problematic to mark `AccessibleObject` as sealed given the existence of several subclasses outside of the JDK.
Solution
--------
Rather than sealing `AccessibleObject`, the public `AccessibleObject` constructor will be marked as deprecated, the need-to-be-overridden methods on `AccessibleObject` will be documented with `implSpec` tags stating the default implementation is to thrown an exception. (Within the JDK, all the `AccessibleObject` subclasses already override these methods, so they would not need to be documented if `AccessibleObject` could be sealed.)
In addition, `Executable` is sealed, permitting its two existing final subclasses, Method and Constructor.
Specification
-------------
diff --git a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
index a3346b8c3f80..560b93f82365 100644
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -497,6 +497,7 @@ public final boolean canAccess(Object obj) {
/**
* Constructor: only used by the Java Virtual Machine.
*/
+ @Deprecated(since="17")
protected AccessibleObject() {}
// Indicates whether language-level access checks are overridden
@@ -520,12 +521,16 @@ protected AccessibleObject() {}
* <p> Note that any annotation returned by this method is a
* declaration annotation.
*
+ * @implSpec
+ * The default implementation throws {@link
+ * UnsupportedOperationException}; subclasses should override this method.
+ *
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
@@ -545,12 +550,16 @@ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
* <p> Note that any annotations returned by this method are
* declaration annotations.
*
+ * @implSpec
+ * The default implementation throws {@link
+ * UnsupportedOperationException}; subclasses should override this method.
+ *
* @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
@Override
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
@@ -606,11 +615,15 @@ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
* <p> Note that any annotations returned by this method are
* declaration annotations.
*
+ * @implSpec
+ * The default implementation throws {@link
+ * UnsupportedOperationException}; subclasses should override this method.
+ *
* @since 1.5
*/
@Override
public Annotation[] getDeclaredAnnotations() {
diff --git a/src/java.base/share/classes/java/lang/reflect/Executable.java b/src/java.base/share/classes/java/lang/reflect/Executable.java
index ad399cb86d95..d86a454c7511 100644
--- a/src/java.base/share/classes/java/lang/reflect/Executable.java
+++ b/src/java.base/share/classes/java/lang/reflect/Executable.java
@@ -47,11 +47,12 @@
*
* @since 1.8
*/
-public abstract class Executable extends AccessibleObject
- implements Member, GenericDeclaration {
+public abstract sealed class Executable extends AccessibleObject
+ implements Member, GenericDeclaration permits Constructor, Method {