它可以帮助我们建立类型安全的集合,泛型的本质是数据类型的参数化
泛型提供了编译期间检查数据类型,减少数据类型的转换
在类的声明处增加泛型列表,如:
泛型类
// E:表示泛型 泛型E像一个占位符表示未知的数据类型,在调用的时候传入这个数据类型
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Generic<T> {
private T key;
}
- 泛型类在创建对象时没有指定数据类型,就按照Object类型处理
- 泛型的类型参数只能是类类型,不能是基本数据类型(因为泛型底层在泛型参数编译时是转换成Object去处理,再转换成传入的数据类型;而Object类是不持有基本数据类型的;可以用它们的包装类;Number类是基本数据类型包装类的父类)
- 同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型
泛型类派生子类
- 子类也是泛型类,子类的泛型标识要和父类一致;子类可以进行泛型扩展但至少要有一种类型和父类一样
```java
public class GenericSec
extends Generic { }
public class GenericSec
- **子类不是泛型类,父类要明确泛型的数据类型**
```java
public class GenericSec extends Generic<String>{ }
泛型接口
//泛型接口
public interface Genertor <T>{
T getKey();
}
实现类也是泛型类,实现类和接口的泛型类型要一致
//要保证实现接口的泛型类泛型标识包含泛型接口的泛型标识
public class GenericImp<T,E,V> implements Genertor<T>{
@Override
public T getKey() {
return null;
}
}
实现类不是泛型类,接口要明确数据类型
public class GenericImp implements Genertor<String>{
@Override
public String getKey() {
return null;
}
}
泛型方法
泛型方法上面的
能用泛型方法解决就不要用泛型类(泛型方法独立于泛型类使用)
- 只有声明了
的方法才是泛型方法 ,泛型类中的使用了泛型的成员方法并不是泛型方法(成员方法的泛型遵从泛型类的泛型) < T >表明该方法将使用泛型类型T,此时才可以在方法中或返回值、参数列表内使用泛型类型T
public static <T,E,V> E getPro(List<E> E, T t) {
System.out.println(t);
return E.get(0);
}
泛型方法能使方法独立于类而产生变化
- 如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法
泛型方法与可变参数
public static <E> E get(E... e){
return e[0];
}
类型通配符
使用 ? 代替具体的实参类型; 类型通配符是类型实参,不是类型形参
通配符的上限
要求该泛型的类型,只能是实参类型或者实参类型的子类型
不能在内部填充元素;(不能确定传入的参数类型)
实例:TreeSet(_Collection<_? extends E_> c)_
public static void show(Generic<? extends Number> generic) {
System.out.println(generic.getKey());
}
Generic<Integer> generic = new Generic<>();
generic.setKey(555);
show(generic);
Generic<Number> generic2 = new Generic<>();
generic2.setKey(222);
show(generic2);
通配符的下限
要求该泛型的类型,只能是实参类型或者实参类型的父类型
可以在内部填充元素(填充实参类型或者子类类型);
遍历元素时用的是Object接收
实例:TreeSet(_Comparator<_? super E_> comparator)_
public static void show(Generic<? Super Integer> generic) {
System.out.println(generic.getKey());
}
类型擦除
泛型信息只存在于代码编译阶段, 编译器对参数的简化 ;在进入JVM编译之前 , 与泛型相关的信息会被擦除
ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
//虽然传入数据类型不同,但本质上是同一种类型
System.out.println(list.getClass() == list2.getClass());