1。常用于容器:泛型一种泛化类型,简便类型的检查和转换,不管是存入还是取出(泛型只针对非基本类型)
(ps:适用场景:类型个数不多,又需要不同类型的类。)
2。泛型的定义:声明时不能用static修饰泛型
泛型类:
public class GenericTest<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; }
泛型接口:与类类似,但泛型只能在方法上
泛型方法:泛型定义在返回类型前面
public <S> void m(S s){}
public <S extends List> void m2(S s){ s.add(1); }
3.泛型的擦除
这里说的是主动擦除(用时不用泛型);本质的是编译器检查类型后做的系统擦除。主动擦除基于这种系统擦除,比较简单。
3.1.继承时候不指定类型:
public class GenericTest<T> { private T t; public T getT() { return t; }
class A extends GenericTest{//父类没有泛型被擦除,泛型类型变成Object
@Override
public Object getT() {}}
3.2.使用的时候不指定类型
GenericTest genericTest = new GenericTest();//类型擦除,类型当作Object处理
4.泛型的继承(父类不擦除,子类泛型必须保留除非父类指定类型;子类定义的泛型可以多余父类泛型个数)
class GenericT<T> { T t; void m(T tt) { } }
4.1.明确父类泛型,子类可擦除
class C extends GenericT<String> { // class C extends GenericT<T> 这样报错 在子类中不能确定T类型
@Override void m(String tt) {
4.2.父类不擦除,子类不能擦除
class D<T> extends GenericT<T> { @Override void m(T tt) {
4.3父类擦除,子类擦不擦除都可以
class A extends GenericT { @Override void m(Object tt) { class B<T,S> extends GenericT { @Override void m(Object tt) {
5.泛型没有多态功能【多态形式上即:小类型可以赋值给大类型】:(如果需要类似的功能可以使用泛型通配符实现)
泛型赋值或者传参的时候,小类型泛型不能向大泛型传递。
//可以
GenericT<Object> genericT = new GenericT<Object>(); GenericT genericT2 = new GenericT(); GenericT<String> genericT3 = new GenericT<String>(); GenericT<String> genericT4 = new GenericT(); GenericT genericT7 = new GenericT<String>(); GenericT<Object> genericT5 = new GenericT<String>();//不可以 GenericT<String> genericT6 = new GenericT<Object>();//不可以
//仅仅是因为兼容性考虑泛型和非泛型能够相互转换而不是自动提升类型。 genericT5=genericT7;//可以,因为7认为是非泛型 genericT6=genericT;//不可以
6.多态通配符:? extends super
?:表示类型不定,使用时确定。用于方法参数和声明变量上,不能用在类和new 类<?>上
GenericT<?> genericT8= new GenericT<String>(); void test(GenericT<?> g){ }
extends type: 表示小于等于type类型
static void test(GenericT<? extends Object> g) {} GenericT<? extends Object> genericT8 = new GenericT<String>();
super type : 表示大于等于type类型
7.不能创建泛型数组:
GenericT<String> ge=new GenericT<String>[33];//错误
如果要实现存放泛型的数组形式可以通过自定义类包装数组然后强转。
public class ArrayListTest<T> { Object[] element = new Object[10]; void addT(T t) { element[size++] = t; } T getT(int i) { return (T) element[i]; } public static void main(String[] args) { ArrayListTest<String> a = new ArrayListTest<String>(); a.addT("s"); String t = a.getT(0); }
8.java1.7 泛型新特性,泛型实例化可以简略写<>.
MyArrayList<String> a=new MyArrayLIst<>();
总结一下各种泛型使用环境:(泛型中? super T和? extends T的区别)
如何理解 Java 中的 <T extends Comparable<? super T>>
public class Box<T> { public T t; public T getT() { return t; } public void setT(T t) { this.t = t; } }
public class A {
}
class B extends A{
}
class C extends B{
}
请记住PECS原则:生产者(Producer)使用extends,消费者(Consumer)使用super。
1.<T>:表示某一种(某一特定的类型)泛型。使用时指明具体类型,常见如:集合
2.<?>:表示任何泛型。只能得到Object类型的对象
3.<? extends T>:T和T的子类型 (可以用于从其获取得到T类型)。
一般是方法的参数,可以从引用中获取到T类型的对象(因为引用指向的是包含T子类的任何类型容器,不确定类型,所以不能插入)
或者方法的返回类型
static void readExtends(Box<? extends B> box) { B number = box.getT(); } static void writeExtends2(Box<? extends B> box) { box.setT(null); }
比如:
public class TreeSet<E>
public boolean addAll(Collection<? extends E> c) {
4.<? super T>:T和T的父类型(可以让T类型插入其中)。
一般是方法的参数 ,可以插入T和子类型到引用中,(因为引用指向的是包含T父类的任何类型容器),取出的对象不确定,得到Object对象
方法的返回类型
static void readSuper(Box<? super B> box) { Object object = box.getT(); } static void writeSuper2(Box<? super B> box) { // box.setT(new A()); 错误 box.setT(new B()); box.setT(new C()); }
比如jdk:
public class TreeSet<E> public TreeSet(Comparator<? super E> comparator) {
public class Collections { public static <T extends Comparable<? super T>> void sort(List<T> list) {}
public static <T> void sort(List<T> list, Comparator<? super T> c) {}