简体   繁体   English

由于层次结构中的抽象类,使用反射的递归方法调用失败

[英]Recursive method call that uses reflection fails due to abstract class in hierarchy

I have simplified the issue I'm facing in the SSCCE at the bottom. 我简化了我在底部的SSCCE中面临的问题。

As it is the output is BCD as one would expect. 因为它的输出是BCD正如人们所期望的那样。 If I make, say, C abstract then D gets printed and after that an exception occurs: 如果我说C抽象,那么D将被打印,然后发生异常:

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. 我唯一能想到的解决方案是删除recursiveCall方法,并使classSpecificMethod调用父实现。

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. 为了避免引入冗余和出现错误的可能性,我认为(我从未使用过)我可以在编译时使用AspectJ生成代码。 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. 如果没有其他方法可以使用纯Java做到这一点,我也欢迎使用其他JVM语言和工具的答案。

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"; }
    }
}

You can't create an instance of an abstract class. 您不能创建抽象类的实例。 The only way I see to solve this is by making the recursiveCall() skip abstract classes: 我看到解决此问题的唯一方法是使recursiveCall()跳过抽象类:

private String recursiveCall() {
    String result = "";
    Class<?> parentClass=getClass();
    do {
        parentClass = parentClass.getSuperclass();
    } while (Modifier.isAbstract(parentClass.getModifiers()) && parentClass != A.class);
    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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM