首页 > 有关java泛型中一段简单代码 擦除知识点的疑问

有关java泛型中一段简单代码 擦除知识点的疑问

  1. 下面这个程序中T 类型不是被擦除了吗?为什么使用get ( ) 方法不需要类型装换? (不适用泛型的简单代码就需要加(String) 来实现类型转换)

  2. 擦除知识点在实际编程中体现的多吗?

代码如下:

public class GenericHolder<T> {
  private T obj;
  public void set(T obj) { this.obj = obj; }
  public T get() { return obj; }
  public static void main(String[] args) {
    GenericHolder<String> holder =
      new GenericHolder<String>();
    holder.set("Item");
    String s = holder.get();
  }
}
public class SimpleHolder {
  private Object obj;
  public void set(Object obj) { this.obj = obj; }
  public Object get() { return obj; }
  public static void main(String[] args) {
    SimpleHolder holder = new SimpleHolder();
    holder.set("Item");
    String s = (String)holder.get();
  }
}

GenericHolder<String> 中的

private T obj;
public void set(T obj) { this.obj = obj; }
public T get() { return obj; }

相当于

private String obj;
public void set(String obj) { this.obj = obj; }
public String get() { return (String) obj; }

泛型只在源码中体现,编译后等同于你举例的后者。所以pubic void test(List<String> list)和public void test(List<Integer> list)不能实现重载。


1.首先,擦除通俗的说是指泛型标签是交给Javac编译器去执行的,并起作用的。 代码过完编译期,运行期间就不管了《T》,在class文件找不到T了。 这里你显示了指明了类型是<String>,那么编译器会在编译期间将GenericHolder中持有的T转换成String类型。 所以你的get不用转型了(编译器已经把String识别出来了)。

2.擦除是泛型中很重要的概念,可以说不懂擦除就不懂泛型。实际工作中有常见有关联的是对象的序列化反序列化,如gson等框架中会用到。



擦除是指运行时在泛型类内部无法得到有关泛型参数的任何信息, 如果指定了边界,泛型变量的实际类型就是边界,楼主示例中的代码没有指定边界, 所以擦出到Object, 也就是obj实际运行时的类型为Object, 之所以使用get()方法不需要强制类型转换, 是因为编译期在编译时帮你生成了转换的代码, 如果我没记错的话, 大概处理之后的情况和示例2的main方法中的String s = (String)holder.get()类似, 详细的楼主可以用javap 反编译查看.

对于第二个问题, 我觉着这就和看不看源码是一个道理, 不看也不影响编程, 但是看过之后明白了, 写起来会很得心应手, 我还是学生, 实际编程的情况就不知道啦, 一点点看法~


  1. 擦除是在编译期擦除,将 java 文件编译为 class 文件时擦除。java 的泛型,可以看成一种语法糖,使得我们在书写java代码时更安全便捷。

  2. 擦除在实际工作中没有用到,擦除可以认为是泛型语法糖在编译期的一种解释动作。

【热门文章】
【热门文章】