java和泛型中的继承

时间:2016-08-16 04:38:22

标签: java generics inheritance

我同意,如果不延伸B类,输出就是" 1233"但是为什么如果用A代码扩展B类代码并不编译?

public class SomeClass {

    public static class A {

        public void f(int x){
            System.out.print("1");
        }

        public void f(Object x){
            System.out.print("2");
        }
    }

    public static class B // extends A {

        public <T> void f(T x){
             System.out.print("3");
        }
    }

    public static void main( String[] args){
        A a=new A();
        B b=new B();
        a.f(3);
        a.f("hello");
        b.f(3);
        b.f("hello");
    }
}

3 个答案:

答案 0 :(得分:3)

方法签名导致名称冲突,以下两个方法签名存在名称冲突问题,因为泛型方法实际上并未覆盖前一个方法。在type erasure之后,两者都具有相同的签名。

public <T> void f(T x){...}
public void f(Object x){...}

B中声明的方法不会覆盖A的方法,因为如果方法被认为被覆盖,

  

JLS 8.4.8.1. Overriding (by Instance Methods)

     

在C类中声明或继承的实例方法m C ,覆盖   来自C的另一个方法m A 在A类中声明,iff以下全部   是的:

     
      
  • A是C的超类。
  •   
  • C不继承m A
  •   
  • m C 的签名是m A 签名的子签名(§8.4.2)。   
    ....
  •   

以下是有效的,编译正常,

public static class A {

    public <T> void f(T x) {
        System.out.print("3");
    }
}

public static class B extends A {

    @Override
    public void f(Object x) {
        System.out.print("2");
    }

}

答案 1 :(得分:1)

由于类型擦除问题,您无法编译上述类。

您的基类中的方法是通用的,并且与父类中的f(Object x)匹配。这将在编译时发生。

public void f(Object x){}
public <T> void f(T x){}

请参阅this Oracle documentation有关类型删除的内容。

但是,您可以保留int方法并且编译正常:

class A {
      public void f(int x){
         System.out.print("1");
      }
}

public class B extends A
{
      public <T> void f(T x){
         System.out.print("3");
      }
}

答案 2 :(得分:1)

Java泛型使用类型擦除。 javac在解析时会发生冲突

public <T> void f(T x);
public void f(Object x);

两者在编译器javac方面都是相同的。

添加另一个factorize

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

This limitation is part of the language syntax, not the Java runtime itself. Essentially, this rule is intended to avoid conflicts in legacy code that still uses raw types.

请参考上述答案。