1.为什么需要泛型?泛型是什么?
public class WhyGeneric {
public static void main(String[] args) {
List list = new ArrayList();
list.add("aaa");
list.add(111);
for (int i = 0; i < list.size(); i++) {
String s = (String) list.get(i);
System.out.println(s);
}
}
}
上面例子运行会报ClassCastException错误,list里面放入了String和Integer类型的数据,编译时不报错,读取运行时报错,加上泛型在编译时我们就不能给集合中添加两种以以上类型的数据。
泛型是参数化的类型,在具体使用的过程中才会变成具体的类型。泛型的类型不可以是基本类型,只能是引用类型!
2.泛型擦除
@Test
public void caiChu() {
List<String> L1 = new ArrayList<String>();
List<Integer> L2 = new ArrayList<Integer>();
Class c1 = L1.getClass();
Class c2 = L2.getClass();
if(L1.equals(L2)) {
System.out.println("泛型擦除了");
}
}
输出结果是“泛型擦除了”,证明在字节码中泛型就消失了。
3.泛型的使用:
* 泛型类
/**
* Created by Alsidun on 2018/7/12.
* 泛型类
*/
public class Generic<T> {
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
}
public class TestGenericClass {
public static void main(String[] args) {
Generic<String> gs = new Generic<String>("abc");
Generic<Integer> gi = new Generic<>(1);
System.out.println("传入的参数是 " + gs.getKey());
System.out.println("传入的参数是 " + gi.getKey());
//这里不指定参数类型,那么就是Object
Generic ga = new Generic(1);
Generic gb = new Generic(1.5555);
Generic gc = new Generic(false);
System.out.println("传入的参数是 " + ga.getKey());
System.out.println("传入的参数是 " + gb.getKey());
System.out.println("传入的参数是 " + gc.getKey());
}
}
/*
传入的参数是 abc
传入的参数是 1
传入的参数是 1
传入的参数是 1.5555
*/
上面的例子定义了一个泛型类及它的使用,只有在类实例化时才知道这个类的具体成员参数类型
- 泛型接口
/**
* Created by Alsidun on 2018/7/12.
*/
public interface GenericIntface<T> {
T say();
}
/**
* 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
* AnimalGeneric implements GenericIntface<T> 报错!!!
* @param <T>
*/
class GenericImpl<T> implements GenericIntface<T> {
@Override
public T say() {
return null;
}
}
/**
* 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
*/
class AnimalGeneric implements GenericIntface<String> {
private String[] animal = new String[]{"dog", "cat", "pig"};
@Override
public String say() {
System.out.println("输出狗 " + animal[0]);
return animal[1];
}
public static void main(String[] args) {
AnimalGeneric ag = new AnimalGeneric();
ag.say();
}
}
- 泛型方法
泛型方法是指在调用方法的时候在指明方法的参数类型
public <T> T show(Generic<T> container)
/**
* Created by Alsidun on 2018/7/12.
* 泛型方法
*/
public class GenericFruit {
static class Fruit {
@Override
public String toString(){
return "fruit";
}
}
static class Apple extends Fruit {
@Override
public String toString() {
return "apple";
}
}
static class Animal {
@Override
public String toString() {
return "person";
}
}
static class GenericTest<T> {
public void show1(T t) {
System.out.println("输出 " + t.toString());
}
//此处的泛型可以和泛型类相同也可不同
public <T> void show2(T t) {
System.out.println("输出 " + t.toString());
}
public <E> void show3(E t) {
System.out.println("输出 " + t.toString());
}
}
public static void main(String[] args) {
/*成员方法,变量,内部类同一级别,必须通过类的实例调用
* 静态方法里面不可以访问外部类的非静态变量,普通内部类(都是静态才可访问)
* 静态访问静态
* */
Apple apple = new Apple();
Animal animal = new Animal();
GenericTest<String> gs = new GenericTest<String>();
GenericTest<Fruit> gf = new GenericTest<Fruit>();
gs.show1("abc");
gf.show1(apple);
//gf.show1(animal); 无法编译通过
gf.show2(apple);
gf.show2("qwe");
gf.show2(animal);
gf.show3(apple);
gf.show3(animal);
}
}
这里会输出对应的对象
4.泛型的通配符
使用时不知道类型使用通配符
ArrayList<?>
代表Object
ArrayList<? extends List>
List及其子类
ArrayList<? super List>
List及其父类