泛型的使用
泛型可以使用类、接口、方法
泛型类
类的访问修饰符 class 类名称<泛型>{
}
1 、定义的泛型类,就一定要传入泛型类型实参么?
并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
2、那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢?
由此,我们发现,在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Box),当然,在逻辑上我们可以理解成多个不同的泛型类型。
究其原因,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
泛型只是在编译阶段有效,在运行阶段,泛型就不存在 (泛型擦除)
泛型接口
访问修饰符 interface 接口名称<泛型>{
}
泛型的表示形式:是任意的。但是常用的泛型的表示:T E K V
- 当实现泛型接口的类,未传入泛型实参时:此时实现类也必须是泛型类
- 当实现泛型接口的类,传入泛型实参时:此时实现类就不在是泛型类 泛型有了明确的表示
泛型方法
泛型方法,是在调用方法的时候指明泛型的具体类型
public <T> T genericMethod(){
}
泛型通配符
<? extends T> 上限 这里只能使用T 本身或T的子类/T的子接口/T的实现类
<? super T> 下限 这里只能使用T 本身或着是T的父类/T的父接口
<?> 通配符 不知道是什么类型 相当于Object 这种通配符只能取值 不能存值
相关代码
package org.lanqiao.generic.demo;
/*
* 自定义泛型类
*/
public class Box<T> {
private T data;
String a;
public T getData() {
return data;
}
public void set(T data) {
this.data = data;
}
//泛型方法
public <E> E show(E a) {
return a;
}
public void showInfo(Box<?> box) {
System.out.println(box.data);
}
/*public void setData(Box<?> box) {
this.data = box.data;
}*/
}
package org.lanqiao.generic.demo;
import java.util.ArrayList;
import java.util.List;
public class BoxTest {
public static void main(String[] args) {
Box<String> b = new Box<>();
b.set("aa");
System.out.println(b.getData());
Box<Integer> bb = new Box<>();
bb.set(1);
String s = bb.show("aa");
System.out.println(s+"============");
System.out.println(bb.getData());
/*Box bbb = new Box();
bbb.set(22);
bbb.set("aaa");*/
System.out.println(b.getClass());
System.out.println(bb.getClass());
List<String> l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
System.out.println(l1.getClass());
System.out.println(l2.getClass());
System.out.println("-----------------------");
Box<Integer> bo = new Box<>();
bo.set(21);
bo.showInfo(bo);
Box<String> bobo = new Box<>();
bobo.set("aaa");
//bobo.showInfo(bobo);
System.out.println("-----------------------");
Box<Integer> box1 = new Box<>();
Box<Double> box2 = new Box<>();
Box<String> box3 = new Box<>();
box3.set("aaa");
box2.set(34.34);
box1.set(34);
box1.showInfo(box2);
box1.showInfo(box3);
}
}
package org.lanqiao.generic.demo;
public interface GenericInterfaceDemo<addfdsaf> {
public addfdsaf getData();
public addfdsaf showInfo();
}
package org.lanqiao.generic.demo;
public class GenericInterfaceDemoInImpl<T> implements GenericInterfaceDemo<T> {
@Override
public T getData() {
// TODO Auto-generated method stub
return null;
}
@Override
public T showInfo() {
// TODO Auto-generated method stub
return null;
}
}
泛型擦除
在编译后所有的泛型类型都会做相应的转化,转化如下:
List<String>、List<T> 擦除后的类型为 List。
List<String>[]、List<T>[] 擦除后的类型为 List[]。
List<? extends E>、List<? super E> 擦除后的类型为 List<E>。