Java中泛型学习之细节篇
泛型擦除
在Java中,泛型实现是基于类型擦除的。
当我们在定义一个泛型类或泛型方法时,编译器会将其中的参数类型替换成Object类型。这意味着,在运行时,我们无法再获取原始的参数类型。
举个例子,下面这个泛型类在编译后会被擦除:
public class Generic<T> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
在编译后,泛型类型会被替换成Object类型,代码如下:
public class Generic {
private Object t;
public Object get() {
return t;
}
public void set(Object t) {
this.t = t;
}
}
因此,我们在实例化泛型对象时,不能使用原始类型,如:
Generic<Integer> g = new Generic<>(); // 编译错误
应该使用引用类型:
Generic<Integer> g = new Generic<Integer>();
泛型的上下限
Java中泛型还有一个重要的概念:上下限。
在使用泛型时,我们有时候希望泛型参数类型是一个特定的类型或其子类型,或者是一个特定的类型或其父类型。这时就可以使用泛型的上下限。
上限
上限用extends关键字声明,表示泛型参数类型必须是指定类型或其子类型。示例如下:
public class Generic<T extends Number> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
// 实例化Generic
Generic<Integer> intObj = new Generic<Integer>(); // 编译通过,T是Number的子类Integer
Generic<String> strObj = new Generic<String>(); // 编译错误,T不是Number的子类
在上面的示例中,泛型参数类型T必须是Number的子类,因此可以实例化一个泛型对象Generic
下限
下限用super关键字声明,表示泛型参数类型必须是指定类型或其父类型。示例如下:
public class Generic<T> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
public void process(List<? super Integer> list) {
// 处理过程
}
}
// 实例化Generic
Generic<Object> obj = new Generic<Object>(); // 编译通过,Integer是Object的子类
Generic<Number> num = new Generic<Number>(); // 编译通过,Integer是Number的子类
Generic<Integer> i = new Generic<Integer>(); // 编译错误,Integer不是Integer的父类
在上面的示例中,process方法接收一个<? super Integer>类型的List对象,表示List中的元素必须是Integer的父类。因此,可以将List
总结
Java中泛型学习之细节篇主要讲解了泛型擦除和泛型的上下限。了解泛型的概念和用法对于提高Java编程效率具有非常重要的意义。
以上仅为简单示例,更多关于Java泛型的细节问题,如泛型数组、泛型空包装类等,可进一步深入学习。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中泛型学习之细节篇 - Python技术站