Java 两种方法具有相同的擦除

Java 两种方法具有相同的擦除,java,generics,overriding,Java,Generics,Overriding,我读过类似的问题,知道一般的擦除会在同一个类中导致这个错误。但我不明白为什么下面的代码不起作用 我设计了一些例子。发现很多事情让人困惑 public static class Father<S> { public void foo(Set<String> s) {...} public void bar(S s) {...} public void baz(String s) {...} } public static class Son

我读过类似的问题,知道一般的擦除会在同一个类中导致这个错误。但我不明白为什么下面的代码不起作用

我设计了一些例子。发现很多事情让人困惑

public static class Father<S> {

    public void foo(Set<String> s) {...}

    public void bar(S s) {...}

    public void baz(String s) {...}
}


public static class Son<E> extends Father {

    public void foo(Set<String> s) {...} **// error**

    public void bar(E e) {...} **// error**
 // public void bar(Object e) {...} // This works

    public void baz(String s) {...}
}


public static class Daughter<E> extends Father<T> {

    public void foo(Set<String> s) {...} **// error**

    public void bar(Object e) {...}

    public void baz(String s) {...} **// error**
}
公共静态类父类{
公共void foo(集s){…}
公共空白栏{…}
公共void baz(字符串s){…}
}
公共静态类子扩展父{
公共void foo(集合s){…}**//错误**
公共无效条(E){…}**//错误**
//公共空栏(对象e){…}//这是有效的
公共void baz(字符串s){…}
}
公共静态类女儿延伸到父亲{
公共void foo(集合s){…}**//错误**
公共空栏(对象e){…}
公共void baz(字符串s){…}**//错误**
}
正如你所看到的,我犯了几个错误。以下是我的问题:

  • 让我们关注父亲和儿子。为什么
    baz
    有效,而
    foo
    无效
  • 让我们看看
    Son
    中的
    bar
    。为什么
    objecte
    工作,而
    ee
    失败?我想
    E
    将被擦除为
    对象
  • 让我们看看
    ,为什么
    baz
    相比失败了
  • 请告诉我为什么会发生这种情况?非常感谢!
    (我知道我不应该使用原始类。但这为什么会导致错误?

    问题是
    Son
    扩展了原始
    父类

    因此,
    Son
    类的
    foo
    bar
    不会覆盖

    public void foo(Set<String> s) {}
    
    public void bar(S s) {}
    
    并对
    Son
    类中同名的方法进行相同的擦除

    将子的声明更改为

    public static class Son<E> extends Father<E>
    
    公共静态类子扩展父类
    
    将解决错误

    baz
    方法没有问题,因为它没有泛型参数,所以子类的
    baz
    覆盖基类的
    baz

    在你的
    女儿
    班上,不清楚
    T
    来自哪里。如果将
    T
    更改为
    E
    ,所有错误都会消失

    噢,
    void bar(Object e)
    在原始示例中起作用,因为它覆盖了
    父对象的
    void bar
    (由于
    子对象扩展了原始
    父对象)

    public class Son<E> extends Father {
    
    使用原始类型也会对继承性产生影响。
    从:

    原始类型的超类(分别是超接口)是 删除任何 泛型类型的参数化

    以及:

    类的超类型可以是原始类型。用户的成员访问权限 类被视为正常,并且超类型的成员访问被忽略 作为原始类型处理

    因此,<代码>子< /代码>不考虑父类中的泛型。
    对于

    Son
    ,此继承方法:

    public void foo(Set<String> s) {
    }
    
    因此,子方法和父方法具有相同的擦除,但子方法不会重写父方法,因为您使用的类型不完全相同:

    public void foo(Set<String> s) {...} **// error**
    
    它将编译

    对于带有泛型的
    bar()
    方法,情况完全相同

    这:

    public void bar(E e) 
    
    将约束为:

    public void foo(Set s) {
    }
    
    public void bar(Object e) 
    
    你也会遇到同样的问题

    我不会解释所有要点,因为我认为这没有帮助。
    你得到的是坏习惯的结果。

    士气在于您不必为设计用于泛型的类使用原始类型,因为这可能会对它们的初始意图和类的使用产生严重的副作用。

    这个

    公共静态类子扩展父类{
    
    应该是:

    public static class Son<E> extends Father<E>  {
    
    public static class Daughter<E> extends Father<E> {
    
    公共静态类子扩展父类{
    
    这是:

    public static class Daughter<E> extends Father<T> {
    
    公共静态类子类扩展父类{
    
    应该是:

    public static class Son<E> extends Father<E>  {
    
    public static class Daughter<E> extends Father<E> {
    
    公共静态类子类扩展父类{
    
    T.T我知道我不应该使用原始类。但我真的想知道它为什么会导致错误。
    public static class Daughter<E> extends Father<T> {
    
    public static class Daughter<E> extends Father<E> {