一、泛型概念
所谓泛型,就是允许自定义类,接口通过一个标识类中的某个属性的类型或者是某个方法的返回值及参数类型。
这个类型参数将在使用时.(例如,继承或实现这个接口,用这个类型声明变量、创建对象时确定(即传入实际类型参数,也称类型实参))。
二、泛型的引用背景
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在 JDK1.5 之前只能把元素类型设计为 object,JDK1.5 之后使用泛型类解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个这个元素如何保存的,如何管理等使确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection,List 这个就是类型参数,即泛型。
三、泛型在集合中的使用
1、没有使用泛型之前
图示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test public void test1(){ ArrayList list = new ArrayList(); list.add(78); list.add(76); list.add(89); list.add(88);
for (Object obj : list) { int stuScore = (Integer) obj; System.out.println(stuScore); } }
|
2、使用泛型
图示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Test public void test2(){ ArrayList<Integer> list = new ArrayList<>();
list.add(78); list.add(87); list.add(99); list.add(65); Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ Integer next = iterator.next(); System.out.println(next); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Test public void test3(){ HashMap<String, Integer> map = new HashMap<>();
map.put("Tom",87); map.put("Jerry",87); map.put("Jack",67);
Set<Map.Entry<String, Integer>> entries = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entries.iterator(); while(iterator.hasNext()){ Map.Entry<String, Integer> e = iterator.next(); String key = e.getKey(); Integer value = e.getValue(); System.out.println(key +"-->" + value); } }
|
3、集合中使用泛型总结
- 集合接口或集合类在 JDk 5.0 时都修改带泛型的结构。
- 在实例化集合类时,可以指明具体的泛型类型
- 指明完以后,在集合或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
- 比如:add(E e) —> 实例化必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
- 如果实例化时,没指明泛型的类型。默认类型为 java.Object 类型。
四、自定义泛型类、泛型接口、泛型方法
【Order.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class Order<T> { String orderName; int orderId;
T orderT;
public Order(){ T[] arr = (T[]) new Object[10]; }
public Order(String orderName, int orderId, T orderT) { this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; }
public T getOrderT() { return orderT; }
public void setOrderT(T orderT) { this.orderT = orderT; }
@Override public String toString() { return "Order{" + "orderName='" + orderName + '\'' + ", orderId=" + orderId + ", orderT=" + orderT + '}'; }
public static <E>List<E> copyFormArrayTolist(E[] arr){ ArrayList<E> list = new ArrayList<>(); for(E e : arr){ list.add(e); } return list; } }
|
注意:
- 静态方法中不能使用类的泛型。
- 泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没任何关系。
- 换句话说,泛型方法所属的类是不是泛型类都没关系。
- 泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。
【SubOrder.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class SubOrder extends Order<Integer> {
public static <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e : arr){ list.add(e); } return list;
} }
|
注意:实例化时,如下的代码是错误的
1
| SubOrder<Integer> o = new SubOrder<>();
|
【测试】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class OrderTest { @Test public void test1(){ Order order = new Order(); order.setOrderT(123); order.setOrderT("abc");
Order<String> order1 = new Order<>("orderAA",1001,"order:AA");
order1.setOrderT("AA:hello"); }
@Test public void test2(){ SubOrder sub1 = new SubOrder(); sub1.setOrderT(1122);
}
@Test public void test3(){ Order<String> order = new Order<>(); Integer[] arr = {1, 2, 3, 4, 5}; List<Integer> list = order.copyFormArrayTolist(arr); System.out.println(list); } }
|
五、注意点
六、通配符的使用
通配符:?
类 A 是类 B 的父类,G<A>和 G<B>是没关系的,二者共同的父类是:G<?>
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Test public void test(){ List<Object> list1 = null; List<String> list2 = null;
List<?> list = null;
list = list1; list = list2;
System.out.println(list1); System.out.println(list2); }
|
运行结果:
有限制条件的通配符的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
@Test public void test4(){
List<? extends Person> list1 = null; List<? super Person> list2 = null;
List<Student> list3 = new ArrayList<Student>(); List<Person> list4 = new ArrayList<Person>(); List<Object> list5 = new ArrayList<Object>();
list1 = list3; list1 = list4;
list2 = list4; list2 = list5;
list1 = list3; Person p = list1.get(0);
list2 = list4; Object obj = list2.get(0);
list2.add(new Person()); list2.add(new Student());
}
|