Java 静态方法和继承的返回类型中的泛型

Java 静态方法和继承的返回类型中的泛型,java,generics,inheritance,static-methods,Java,Generics,Inheritance,Static Methods,静态方法的返回类型中的泛型似乎与继承关系不太好。请查看以下代码: class ClassInfo<C> { public ClassInfo(Class<C> clazz) { this(clazz,null); } public ClassInfo(Class<C> clazz, ClassInfo<? super C> superClassInfo) { } } class A { public stat

静态方法的返回类型中的泛型似乎与继承关系不太好。请查看以下代码:

class ClassInfo<C>  {
  public ClassInfo(Class<C> clazz) {
    this(clazz,null);
  }  
  public ClassInfo(Class<C> clazz, ClassInfo<? super C> superClassInfo) {
  }
}

class A {
    public static ClassInfo<A> getClassInfo() {
        return new ClassInfo<A>(A.class);
    }
}

class B extends A {
    // Error: The return type is incompatible with A.getClassInfo()
    public static ClassInfo<B> getClassInfo() { 
        return new ClassInfo<B>(B.class, A.getClassInfo());
    }
}
ClassInfo类{
公共ClassInfo(类别分类){
这个(clazz,null);
}  

public ClassInfo(Class clazz,ClassInfo您不能重写静态方法。因此,当您声明相同的静态方法时,您正在创建一个新方法

public static ClassInfo<B> getClassInfo() { 
    return new ClassInfo<B>(B.class, A.getClassInfo());
}
publicstaticclassinfo getClassInfo(){
返回新的ClassInfo(B.class,A.getClassInfo());
}
但是,当您使用更改的返回类型声明方法时,不是有效的隐藏方法,也不是覆盖方法
B类的方法
,相互冲突。因为A类的方法在B类中也可见

因此,换句话说,
类B
具有相同的方法,因为它继承自
类A
,返回类型发生了变化。并且由于方法的返回类型不被视为方法签名的一部分。因此冲突


因此,您需要具有完全相同的返回类型。在这种情况下,类B将忽略继承的方法,并使用它自己的方法。

B中的静态方法不会覆盖A中的静态方法,而是将其隐藏。明确说明返回类型必须是可替换的,否则它不会编译:

如果返回类型为R1的方法声明d1重写或隐藏另一个返回类型为R2的方法d2的声明,则d1必须是d2的可替换返回类型(§8.4.5),否则会发生编译时错误

可替代性的定义见JLS第8.4.5节:

当且仅当以下条件成立时,返回类型为R1的方法声明d1可替换为返回类型为R2的另一方法d2:

  • [……]
  • 如果R1是引用类型,则:
    • R1是R2的子类型,或者R1可以通过未经检查的转换(§5.1.9)转换为R2的子类型,或者
    • R1=| R2|
在您的案例中:d1是B中的方法,R1是
ClassInfo
,d2是A中的方法,R2是
ClassInfo
。并且
ClassInfo
不是
ClassInfo
的子类型


然而,
ClassInfo但是为什么我的第二个示例中的声明可以工作呢?我得到的错误是调用
ClassInfo
构造函数,如果我将其更改为
return new ClassInfo(B.class),(ClassInfo因为
扩展了A
也覆盖了B类,
超级B
也覆盖了B类。因此,它可以工作。
public static ClassInfo<B> getClassInfo() { 
    return new ClassInfo<B>(B.class, A.getClassInfo());
}
void someMethod(){
    ClassInfo<B> b1 = (ClassInfo<B>) get1(); //does not compile
    ClassInfo<? extends B> b2 = (ClassInfo<? extends B>) get2(); //compiles
}

ClassInfo<A> get1() {
    return null;
}

ClassInfo<? extends A> get2() {
    return null;
}