Class VirtualMethod<C>
Before the replacement method can be made abstract, the old method must kept deprecated. If somebody still overrides the deprecated method in a non-final class, you must keep track, of this and maybe delegate to the old method in the subclass. The cost of reflection is minimized by the following usage of this class:
Define static final fields in the base class (BaseClass), where the
old and new method are declared:
static final VirtualMethod<BaseClass> newMethod = new VirtualMethod<BaseClass>(BaseClass.class, "newName", parameters...); static final VirtualMethod<BaseClass> oldMethod = new VirtualMethod<BaseClass>(BaseClass.class, "oldName", parameters...);
This enforces the singleton status of these objects, as the maintenance of the cache would be
too costly else. If you try to create a second instance of for the same method/baseClass
combination, an exception is thrown.
To detect if e.g. the old method was overridden by a more far subclass on the inheritance path to the current instance's class, use a non-static field:
final boolean isDeprecatedMethodOverridden =
AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
(oldMethod.getImplementationDistance(this.getClass()) > newMethod.getImplementationDistance(this.getClass())));
// alternatively (more readable):
final boolean isDeprecatedMethodOverridden =
AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
VirtualMethod.compareImplementationDistance(this.getClass(), oldMethod, newMethod) > 0);
It is important to use AccessController.doPrivileged(PrivilegedAction) for the actual
call to get the implementation distance because the subclass may be in a different package. The
static constructors do not need to use AccessController because it just initializes our
own method reference. The caller should have access to all declared members in its own class.
getImplementationDistance(java.lang.Class<? extends C>) returns the distance of the subclass that overrides this
method. The one with the larger distance should be used preferable. This way also more
complicated method rename scenarios can be handled (think of 2.9 TokenStream
deprecations).
- NOTE: This API is for internal purposes only and might change in incompatible ways in the next release.
-
Constructor Summary
ConstructorsConstructorDescriptionVirtualMethod(Class<C> baseClass, String method, Class<?>... parameters) Creates a new instance for the givenbaseClassand method declaration. -
Method Summary
Modifier and TypeMethodDescriptionstatic <C> intcompareImplementationDistance(Class<? extends C> clazz, VirtualMethod<C> m1, VirtualMethod<C> m2) Utility method that compares the implementation/override distance of two methods.intgetImplementationDistance(Class<? extends C> subclazz) Returns the distance from thebaseClassin which this method is overridden/implemented in the inheritance path betweenbaseClassand the given subclasssubclazz.booleanisOverriddenAsOf(Class<? extends C> subclazz) Returns, if this method is overridden/implemented in the inheritance path betweenbaseClassand the given subclasssubclazz.
-
Constructor Details
-
VirtualMethod
Creates a new instance for the givenbaseClassand method declaration.- Throws:
UnsupportedOperationException- if you create a second instance of the samebaseClassand method declaration combination. This enforces the singleton status.IllegalArgumentException- ifbaseClassdoes not declare the given method.
-
-
Method Details
-
getImplementationDistance
Returns the distance from thebaseClassin which this method is overridden/implemented in the inheritance path betweenbaseClassand the given subclasssubclazz.- Returns:
- 0 iff not overridden, else the distance to the base class
-
isOverriddenAsOf
Returns, if this method is overridden/implemented in the inheritance path betweenbaseClassand the given subclasssubclazz.You can use this method to detect if a method that should normally be final was overridden by the given instance's class.
- Returns:
falseiff not overridden
-
compareImplementationDistance
public static <C> int compareImplementationDistance(Class<? extends C> clazz, VirtualMethod<C> m1, VirtualMethod<C> m2) Utility method that compares the implementation/override distance of two methods.- Returns:
- > 1, iff
m1is overridden/implemented in a subclass of the class overriding/declaringm2 - < 1, iff
m2is overridden in a subclass of the class overriding/declaringm1 - 0, iff both methods are overridden in the same class (or are not overridden at all)
- > 1, iff
-