Java 泛型
1. 为什么要有泛型(Generic)?
1. 解决元素存储的安全性问题
2. 解决获取数据元素时,需要类型强转的问题
2. 使用泛型
1.泛型的声明
interface List<T> 和 class TestGen<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。常用T表示,是Type的缩写。
2. 泛型的实例化:
一定要在类名后面指定类型参数的值(类型)。如:
List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
T只能是类,不能用基本数据类型填充。
1.在集合中使用泛型(掌握)
2.自定义泛型类、泛型接口、泛型方法(理解 --->使用)
3.泛型与继承的关系
4.通配符
1.在集合中使用泛型
1.对象实例化时不指定泛型,默认为:Object。
2.泛型不同的引用不能相互赋值。
3.加入集合中的对象类型必须与指定的泛型类型一致。
4.静态方法中不能使用类的泛型。
5.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。
6.不能在catch中使用泛型
7.从泛型类派生子类,泛型类型需具体化
把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想。
2. 自定义泛型类
public class Order<T> { private String orderName; private int orderId; private T t; List<T> list = new ArrayList<>(); public void add(){ list.add(t); } public T getT(){ return t; } public void setT(T t){ this.t = t; } //不可以在static方法中使用泛型的声明 // public static void show(){ // System.out.println(t); // } public void info(){ //不可以在try-catch中使用类的泛型的声明 // try{ // // }catch(T e){ // // } } //声明泛型方法 public static <E> E getE(E e){ return e; } //实现数组到集合的复制 public <E> List<E> fromArrayToList(E[] e,List<E> list){ for(E e1 : e){ list.add(e1); } return list; } }
1.当实例化泛型类的对象时,指明泛型的类型。指明以后,对应的类中所有使用泛型的位置,都变为实例化中指定的泛型的类型
2.如果我们自定义了泛型类,但是在实例化时没有使用,那么默认类型是Object类的
3 对于泛型方法
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
当通过对象调泛型方法时,指明泛型方法的类型。
4 泛型和继承的关系
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G<B>并不是G<A>的子类型!
比如:String是Object的子类,但是List<String >并不是List<Object>的子类。
//继承泛型类或泛型接口时,可以指明泛型的类型 class SubOrder extends Order<Integer>{ }
5 通配符 ?
1.使用类型通配符:?
比如:List<?> ,Map<?,?>
List<?>是List<String>、List<Object>等各种泛型List的父类。
2.读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
3.写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。
唯一的例外是null,它是所有类型的成员。
4. 有限制的通配符
<? extends Number> (无穷小 , Number]
只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大)
只允许泛型为Number及Number父类的引用调用
<? extends Comparable>
只允许泛型为实现Comparable接口的实现类的引用调用