在Java中键入擦除意外行为

gga*_*zor 3 java generics

根据Java关于类型擦除有界类型参数的文档,我理解在下面的代码示例中,两个版本doStuff()将具有相同的擦除,因此不会编译.我的目标是超载doStuff()以接收ClassOne和收集ClassTwo.

import java.util.List;

class Example {
  class ClassOne {
  }

  class ClassTwo {
  }

  public void doStuff(List<ClassOne> collection) {
  }

  public void doStuff(List<ClassTwo> collection) {
  }
}
Run Code Online (Sandbox Code Playgroud)

类型擦除的机制包括以下步骤:

· 如果类型参数是无界的,则泛型或对象替换泛型类型中的所有类型参数.因此,生成的字节码仅包含普通的类,接口和方法.

因此,我应该能够应用一个绑定,然后它将编译,因为现在类型擦除版本的doStuff重载了两个不同的签名(声明的上限).例:

class Example {
  class ClassOne {
  }

  class ClassTwo {
  }

  public <U extends ClassOne> void doStuff(List<U> collection) {
  }

  public <U extends ClassTwo> void doStuff(List<U> collection) {
  }
}
Run Code Online (Sandbox Code Playgroud)

第二个例子实际上没有编译并给出以下错误:

错误:(15,36)java:name clash:doStuff(java.util.List)和doStuff(java.util.List)具有相同的擦除

任何人都可以向我解释这个吗?

Kep*_*pil 8

问题是,这List<U>将减少到List你的两种方法.(擦除后你不能拥有List<ClassOne>List<Object>离开.)

您引用的段落意味着可以拥有以下声明:

class Example {
    class ClassOne {
    }

    class ClassTwo {
    }

    public <U extends ClassOne> void doStuff(U foo) {
    }

    public <U extends ClassTwo> void doStuff(U foo) {
    }
}
Run Code Online (Sandbox Code Playgroud)

这里泛型参数将分别替换为ClassOneClassTwo,它们可以正常工作.

  • 简单明了的解释.+1 (2认同)