Rumah > Soal Jawab > teks badan
下面这个程序中T 类型不是被擦除了吗?为什么使用get ( ) 方法不需要类型装换? (不适用泛型的简单代码就需要加(String) 来实现类型转换)
擦除知识点在实际编程中体现的多吗?
代码如下:
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();
}
}
伊谢尔伦2017-04-17 17:37:11
擦除是指运行时在泛型类内部无法得到有关泛型参数的任何信息, 如果指定了边界,泛型变量的实际类型就是边界,楼主示例中的代码没有指定边界, 所以擦出到Object, 也就是obj实际运行时的类型为Object, 之所以使用get()方法不需要强制类型转换, 是因为编译期在编译时帮你生成了转换的代码, 如果我没记错的话, 大概处理之后的情况和示例2的main方法中的String s = (String)holder.get()
类似, 详细的楼主可以用javap 反编译查看.
对于第二个问题, 我觉着这就和看不看源码是一个道理, 不看也不影响编程, 但是看过之后明白了, 写起来会很得心应手, 我还是学生, 实际编程的情况就不知道啦, 一点点看法~
阿神2017-04-17 17:37:11
泛型只在源码中体现,编译后等同于你举例的后者。所以pubic void test(List<String> list)和public void test(List<Integer> list)不能实现重载。
天蓬老师2017-04-17 17:37:11
擦除是在编译期擦除,将 java 文件编译为 class 文件时擦除。java 的泛型,可以看成一种语法糖,使得我们在书写java代码时更安全便捷。
擦除在实际工作中没有用到,擦除可以认为是泛型语法糖在编译期的一种解释动作。
怪我咯2017-04-17 17:37:11
使用泛型类T new的时候指定了T 为String其成员变量也就为String 不需要转型, 而另一个类为成员为Object,new
的时候并未指定,所以需要转型。
擦除实际工作上一般不用。
黄舟2017-04-17 17:37:11
1.首先,擦除通俗的说是指泛型标签是交给Javac编译器去执行的,并起作用的。 代码过完编译期,运行期间就不管了《T》,在class文件找不到T了。 这里你显示了指明了类型是<String>,那么编译器会在编译期间将GenericHolder中持有的T转换成String类型。 所以你的get不用转型了(编译器已经把String识别出来了)。
2.擦除是泛型中很重要的概念,可以说不懂擦除就不懂泛型。实际工作中有常见有关联的是对象的序列化反序列化,如gson等框架中会用到。
怪我咯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();
其实就是个语法糖