允许在定义类、接口时通过一个标识表示类中某个属性的类型、方法返回值、参数类型。这个标识将在使用时确定。 参数T必须为类,且可为多个。
ArrayList<Integer> list = new ArrayList<>();//类型推断,该集合仅可存储Integer类型数据list.add(78);Iterator<Integer> iterator = list.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}
8.1 自定义泛型结构—类
// 自定义泛型类,指明参数Tpublic class order<T>{String orderName;T orderT;public Order(){}public Order(String orderName,T orderT){this.orderName = orderName;this.orderT = orderT;}public T orderT(){return orderT;}}// 实例化未指明参数类型时,默认为Object类型Order order = new Order();order.setOrderT(123);order.setOrderT("123");// 实例化指明参数类型(建议),则参数类型特定Order<String> order1 = new Order<String>();//order1.setorderT(123); 报错,仅可为String// 定义泛型类,class Person<T extends Info>{}
泛型不同的引用不能相互赋值,泛型要使用就一路都用,要不用就一路都不用。
例如:类A是类B的父类,G<A>与G<B>不具备子父类关系,二者为并列关系,共同的父类是G<?>类A是类B的父类,A<G>是B<G>的父类
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,在静态方法中不能使用类的泛型。
- 异常类不能是泛型。
泛型数组的声明:
T[] arr = new T[10]; // 编译不通过T[] arr = (T[])new Object[10]; // 编译通过
子类与父类中的泛型 ```java class Father
{}
// 子类不保留父类的泛型 // 1)没有类型 擦除 class Son1 extends Father {// 等价于class Son extends Father
// 子类保留父类的泛型
// 1)全部保留
class Son3
<a name="uRyFm"></a>## 8.2 自定义泛型结构--方法泛型方法在调用时才指明参数的类型,可以是static的,因为泛型确定与是否为类、对象是没有关系的。<br />`[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称])````javapublic <E> List<E> copyFromArrayToList(E[] arr){ArrayList<E> list = new ArrayList<>();for(E e:arr)list.add(e);return list;}
8.3 通配符
类型通配符?用于所有泛型的引用。如:List<?>是List<String>、List<Object>等各种泛型List的父类。
读取List<?>中的元素永远都是安全的,因为不论其真实类型是什么其包含的都是Object,所以读出的数据也是Object类型。写入元素是不行的,因为不知道其元素类型,因此不能向其添加对象,唯一的例外是null,它是所有类型的成员。
Collection<?> c = new ArrayList<String>();c.add(new Object()); // 编译时错误c.add(null); // 编译通过List<String> l1 = new ArrayList<String>();read(l1);// 通用的List遍历方法public static void read(List<?> list) {for (Object o : list) // 元素一定为Object类型System.out.println(o);}
8.4 有限制条件的通配符
<? extends Number> (无穷小 , Number] // 只允许泛型为Number及Number子类的引用调用<? super Number> [Number , 无穷大) // 只允许泛型为Number及Number父类的引用调用声明下限<? extends Comparable> // 只允许泛型为实现Comparable接口的实现类的引用调用
List<? extends Person> list1 = null; // 可以引用下面的list3和list4List<? super Person> list2 = null; // 可以引用下面的list4和list5List<student> list3 = new ArrayList<student>():List<Person> list4 = new ArrayList<Person>();List<object> list5 = new ArrayList<object>();//读取数据:list1 = list4;Person p= list1.get(0); // 获取的对象类型最小为Person,这是为了满足定义中的引用条件list2 = list4;Object obj = list2.get(0); // 获取的对象类型最小为Object,这是为了满足定义中的引用条件//写入数据//list1.add(new Person()); // 子类可能无穷小,因此extends界限不能添加类型list2.add(new Student()); // Person为下界,最大为Person,子类即父类,因此Person及其子类均可
