首页  >  问答  >  正文

有关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();
  }
}
ringa_leeringa_lee2713 天前766

全部回复(6)我来回复

  • 伊谢尔伦

    伊谢尔伦2017-04-17 17:37:11

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

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

    回复
    0
  • 阿神

    阿神2017-04-17 17:37:11

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

    回复
    0
  • 天蓬老师

    天蓬老师2017-04-17 17:37:11

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

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

    回复
    0
  • 怪我咯

    怪我咯2017-04-17 17:37:11

    • 使用泛型类T new的时候指定了T 为String其成员变量也就为String 不需要转型, 而另一个类为成员为Object,new
      的时候并未指定,所以需要转型。

    • 擦除实际工作上一般不用。

    回复
    0
  • 黄舟

    黄舟2017-04-17 17:37:11

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

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

    回复
    0
  • 怪我咯

    怪我咯2017-04-17 17:37:11

    GenericHolder<String> 中的

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

    相当于

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

    其实就是个语法糖

    回复
    0
  • 取消回复