泛型类、泛型接口和泛型方法
泛型类
/**
* 泛型类
* 创建对象时指定类型
*/
public class NormalGeneric<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static void main(String[] args) {
NormalGeneric<String> normalGeneric = new NormalGeneric<>();
normalGeneric.setData("OK");
String result = normalGeneric.getData();
}
}
泛型接口
/**
* 泛型接口
*/
public interface IGeneric<T> {
public T next();
}
/**
* 不指定具体类型
*/
public class IGenericImpl<T> implements IGeneric<T>{
@Override
public T next() {
return null;
}
}
/**
* 指定具体类型
*/
public class IGenericSpecificTypeImpl implements IGeneric<String>{
@Override
public String next() {
return null;
}
}
泛型方法
/**
* 泛型方法,该方法如果在泛型类中,如果类指定的泛型也是 T,他们互不影响
* 使用方法时指定类型
*/
public <T> T genericMethod(T a){
return a;
}
如何限定类型变量
/**
* 限定 T 必须实现 Comparable
* 使用 & 符号可以指定多个限定类型
* 类和接口混用,类必须在第一个且只能有一个,接口可以有多个
*/
public <T extends Comparable> T min(T a,T b){
return a.compareTo(b) > 0? b:a;
}
泛型使用中的约束和局限性
不能实例化类型变量
静态域或静态方法不能应用类型变量
不允许使用 instanceof
不能捕获泛型类型对象
泛型类型继承规则
public class Carbon {
}
public class Person extends Carbon{
}
public class Man extends Person{
}
public class Pair<T> {
}
Pair<Person> 和 Pair<Man> 没有任何继承关系
Pair<Person> person = new Pair<>();
Pair<Man> man = new Pair<>();
泛型中通配符类型
?为通配符,出现在方法行参数,解决调用 print 不能传入 Pair<Man> 类型问题
public static void print(Pair<? extends Person> p){
}
可以传入 Pair<Person>、Pair<Carbon>,不能传入 Pair<Man>
public static void print(Pair<? super Person> p){
}
set 和 get 方法中的使用
extends 用于安全的访问数据
super 用于安全的写入数据,可以安全的写入 Person 和 Person 的子类
虚拟机是如何实现泛型的
泛型擦除
擦除前
public class NormalGeneric<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
擦除后
public class NormalGeneric<Object> {
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
T extends Comparable&Serializable 擦除后的类型是 Comparable,在使用 Serializable 的方法时会强转成Serializable
泛型的原始类型记录在 Signature 中