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

St.*_*rio 17 java generics static

我有以下示例:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

IDEONE

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

有人可以解释这种行为吗?

Kon*_*kov 10

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

这里的问题是你将继承与staticJava中的类的功能混合在一起.

为了得到这个工作(正确的),你必须摆脱的static改性剂的.handle()方法,并保持实例TA类.此T实例(在运行时)将是某个特定的子类,AbstractErrorHandler然后将执行实际 .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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @StanAntario Java泛型不是像C++那样的模板.类声明不知道你在其他地方给出的参数化. (3认同)

Rad*_*def 6

4.4.类型变量告诉我们:

X带有bound 的类型变量的成员是出现在声明类型变量的点处的交集类型的成员.T & I1 & ... & InT & I1 & ... & In

因此成员T extends AbstractErrorHandler是成员AbstractErrorHandler.T.handle();是指AbstractErrorHandler.handle();.