I have simplified the issue I'm facing in the SSCCE at the bottom.
As it is the output is B C D
as one would expect. If I make, say, C
abstract then D
gets printed and after that an exception occurs:
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at A.recursiveCall(A.java:22)
at A.entryPoint(A.java:10)
at A.main(A.java:6)
Since some of the classes in the hierarchy will necessarily be abstract then my code breaks.
The only solution I can come up with is to remove the recursiveCall
method and make classSpecificMethod
call the parent implementation.
To avoid the redundancy and possibility for error that this introduces I think (I've never used it) I could use AspectJ to generate the code at compile time. But it seems overkill to me. At least for now since I don't have other uses for it.
If there aren't other ways to do this in plain Java I also welcome answers that use other JVM languages and tools.
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
abstract class A {
public static void main(String[] args) {
new D().entryPoint();
}
void entryPoint() {
System.out.println(recursiveCall());
}
private String recursiveCall() {
String result = "";
Class<?> parentClass = getClass().getSuperclass();
if (parentClass != A.class) {
try {
Constructor<?> baseConstructor = parentClass.getDeclaredConstructor();
baseConstructor.setAccessible(true);
@SuppressWarnings("unchecked")
A baseInstance = (A) baseConstructor.newInstance();
result = baseInstance.recursiveCall() + " ";
}
catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException ex) {
ex.printStackTrace();
}
}
result += classSpecificMethod();
return result;
}
protected abstract String classSpecificMethod();
static class B extends A {
protected String classSpecificMethod() { return "B"; }
}
static class C extends B {
protected String classSpecificMethod() { return "C"; }
}
static class D extends C {
protected String classSpecificMethod() { return "D"; }
}
}
Aucun commentaire:
Enregistrer un commentaire