调用类型变量的基静态方法和派生静态方法

2022-09-03 00:44:19

我有以下示例:

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        A<ConcreteErrorHandler> a = new A<ConcreteErrorHandler>();
        a.m(); //Exception here!
    }

    public static class AbstractErrorHandler {
        public static void handle(){ 
            throw new UnsupportedOperationException("Not implemented");
        }
    }

    public static class ConcreteErrorHandler extends AbstractErrorHandler{
        public static void handle(){ 
            System.out.println("Concrete handler");
        }
    }

    public static class A<T extends AbstractErrorHandler>{
        public void m(){
            T.handle();
        }
    }
}

伊豆酮

为什么调用基类的方法,而不是派生的方法?这些方法的签名是完全相同的。我知道静态方法不会继承,但是在我的情况下不应该抛出编译时错误吗?handle()

有人能解释这种行为吗?


答案 1

这样做的原因是编译器不知道在运行时将替换哪个确切的子类型。这就是为什么它只是将方法调用绑定到方法的原因。AbstractErrorHandlerTT.handle()AbstractErrorHandler.handle()

这里的问题是,您将继承与Java中类的功能混合在一起。static

为了使它正常工作(正确),您必须摆脱方法的修饰符,并在类中保留一个实例。此实例(在运行时)将是 的某个特定子类,然后执行实际方法。static.handle()TATAbstractErrorHandler.handle()

例如:

class Ideone {
    public static void main(String[] args) throws java.lang.Exception {
        A<ConcreteErrorHandler> a = new A<ConcreteErrorHandler>(new ConcreteErrorHandler());
        a.m();
    }

    public static class AbstractErrorHandler {
        public void handle() {
            throw new UnsupportedOperationException("Not implemented");
        }
    }

    public static class ConcreteErrorHandler extends AbstractErrorHandler {
        public void handle() {
            System.out.println("Concrete handler");
        }
    }

    public static class A<T extends AbstractErrorHandler> {

        T instance;

        A(T instance) {
            this.instance = instance;
        }

        public void m() {
            instance.handle();
        }
    }
}

答案 2

4.4. 类型变量告诉我们:

带 bound 的类型变量的成员是出现在声明类型变量的点的交集类型的成员。XT & I1 & ... & InT & I1 & ... & In

因此,的成员是 的成员。 指 。T extends AbstractErrorHandlerAbstractErrorHandlerT.handle();AbstractErrorHandler.handle();


推荐