泛型目录
- 泛型概述
- 什么时候使用泛型
- 泛型在集合中的应用
- 泛型在类中的使用
- 泛型在方法中的应用
- 泛型在接口中的应用
- 泛型的通配符:? 未知类型
- 泛型范围
泛型概述
- Java 1.5v 之后出现的安全机制。
- 将运行时期的问题提前暴露在编译时期
- 避免了强制转换中书写的凌乱代码
- 提高编译时期的安全性
- 翻译用于编译时期,运行时,将会去掉泛型,生成的class文件中是不带泛型的,这个称之为泛型的擦除。
- 泛型擦除,是为了兼容运行时的类加载器。因为泛型是JDK1.5加入的,如果没有擦除,则表示类加载器也需要升级。
- 类型的补偿,在运行时,通过获取元素的类型进行强制转换动作,不需要程序员强制转换,这是因为在编译时,类型被擦除,所以类型转换的过程称之为类型补偿。
- 泛型中不能出现基本类型eg:
什么时候使用泛型
- 当操作的引用数据类型不确定的时候,就使用<>将要操作的引用数据类型传入即可。
- 泛型<>是一个用于接收具体引用数据类型的参数范围。
- 只要用到了带有<>的类和接口,就需要明确数据类型。而且< E >中的E要么是一个类,要么是一个接口,而类和接口第一个字母大写,所以这里习惯使用的是大写的第一个字母,这并不是硬性规定,只是一种比较好的习惯。
- 使用形式,<K,V>
泛型在集合中的应用
- 在使用的类或者接口中,带有泛型的需要明确泛型参数,虽然可以不使用泛型,但那是一个不好的习惯,而且主要也是为了兼容老版本。
List<String> listStr = new ArrayList<>();
listStr.add("str1");
listStr.add("str2");
listStr.add("str3");
Iterator<String> it = listStr.iterator();
while (it.hasNext()) {
System.out.println("item = " + it.next());
}
泛型在类中的使用
- 静态方法不能使用泛型,如果静态方法要使用泛型,则直接把泛型定义在方法上。
- 当类中所使用的引用类型不确定的时候,使用泛型。
- 在类中的应用eg
class Test<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
泛型在方法中的应用
- 将方法定义在方法上eg:
class GenericDemo4 {
public static void main(String[] args) {
Tool tool = new Tool();
//方法中的泛型调用
tool.print(new Integer(3));
tool.print2(new Integer(4),new Float(3.0));
}
}
class Tool {
/**
* 泛型在方法中的使用
*/
public <P> void print(P p) {
System.out.println("p = " + p);
}
/**
* 泛型在方法中的使用2
*/
public <K,V> void print2(K k,V v) {
System.out.println("k = " + k + ",v=" + v);
}
}
- 在方法中调用泛型数据类型的方法
;
class GenericDemo5 {
public static void main(String[] args) {
Util<Student> util = new Util(new Person("deHua",32));
util.printInfo();
Util<Student> util2 = new Util(new Student("chaoWei",35,"001"));
util2.printInfo();
}
}
/**
* 泛型中使用extends 关键字来确定基本类型,否则只可以调用Object中的方法
*/
class Util<T extends Person> {
private T t;
public Util(T t) {
this.t = t;
}
public void printInfo() {
System.out.println("t.name = " + t.getName());
System.out.println("t.age = " + t.getAge());
}
}
class Person {
private String name;
private int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person {
public Student(String name,int age,String classNo) {
super(name,age);
this.classNo = classNo;
}
private String classNo;
}
泛型在接口中的应用
- 泛型接口的定义
interface Test<T>{
public void method(T t);
}
- 实现的接口中依然不确定具体的类型
interface Info<T> {
public void getInfo(T t);
}
/**
* 接口的实现类还是不知道接口泛型的类型,则,在InfoChild中定义泛型,在接口中继续使用
* 某些时候,定义了一样的明细,但是意义已经完全不同,InfoChild<P> 定义了Info<P>中的类型
* 如果碰巧InfoChild<T>则在这里的Info<T> 的类型跟InfoChild<T>中的T一致
*/
class InfoChild<P> implements Info<P> {
@Override
public void getInfo(P t) {
}
}
泛型的通配符:? 未知类型
对类型不确定,并且不对类型进行操作的时候使用
public static void printColl(Collection<?> col){
Iterator<?> it =col.iterator();
//这里没有类型只能使用Object接收
//因为类型提升的关系,将拿不到Collection中的元素的具体方法和类型
Object obj = it.next();
}
- 使用泛型定义
public static <T> void printColl2(Collection<T> col) {
Iterator<T> it = col.iterator();
T t = it.next();
}
泛型范围
- ? extend E :接受E类型或E类型的子类型,上限!
- ? super E :接受E类型或者E类型的父类型,下限!
使用时
一般存元素的时候使用上限
取元素的时候一般使用下限