Java泛型 [TOC]
泛型的概念 1.泛型的概念 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返 回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、 创建对象时确定(即传入实际的类型参数,也称为类型实参)。
2.泛型的引入背景 集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection,List,ArrayList 这个就是类型参数,即泛型。
泛型在集合中的使用 1.在集合中使用泛型之前的例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Test public void test1 () { ArrayList list = new ArrayList(); list.add(78 ); list.add(76 ); list.add(89 ); list.add(88 ); ``` for (Object score : list){ int stuScore = (Integer) score; System.out.println(stuScore); } ``` }
图示:
2.在集合中使用泛型例子1 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 ### ~~~java @Test public void test2 () { ArrayList<Integer> list = new ArrayList<Integer>(); ``` list.add(78 ); list.add(87 ); list.add(99 ); list.add(65 ); ``` ``` ``` Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()){ int stuScore = iterator.next(); System.out.println(stuScore); ~~~ } }
图示:
3.在集合中使用泛型例子2 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 @Test public void test3 () { Map<String,Integer> map = new HashMap<>(); ``` map.put("Tom" ,87 ); map.put("Jerry" ,87 ); map.put("Jack" ,67 ); ``` Set<Map.Entry<String,Integer>> entry = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entry.iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> e = iterator.next(); String key = e.getKey(); Integer value = e.getValue(); System.out.println(key + "----" + value); } }
4.集合中使用泛型总结:
① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
② 在实例化集合类时,可以指明具体的泛型类型
③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
比如:add(E e) —>实例化以后:add(Integer e)
④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
⑤ 如果实例化时,没指明泛型的类型。默认类型为java.lang.Object类型。
自定义泛型类、泛型接口、泛型方法 1.举例: 【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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 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 void show () { } public static <E> List<E> copyFromArrayToList (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 15 16 17 18 19 20 21 22 23 24 25 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; } } SubOrder<Integer> o = new SubOrder<>(); 【SubOrder1.java】 public class SubOrder1 <T > extends Order <T > {}
【测试】 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 48 49 50 51 52 53 @Test public void test1(){ //如果定义了泛型类,实例化没指明类的泛型,则认为此泛型类型为Object类型 //要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型。 Order order = new Order(); order.setOrderT(123); order.setOrderT("ABC"); //建议:实例化时指明类的泛型 Order<String> order1 = new Order<String>("orderAA",1001,"order:AA"); order1.setOrderT("AA:hello"); } @Test public void test2(){ SubOrder sub1 = new SubOrder(); //由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型。 sub1.setOrderT(1122); SubOrder1<String> sub2 = new SubOrder1<>(); sub2.setOrderT("order2..."); } @Test public void test3(){ ArrayList<String> list1 = null; ArrayList<Integer> list2 = new ArrayList<Integer>(); //泛型不同的引用不能相互赋值。 // list1 = list2; Person p1 = null; Person p2 = null; p1 = p2; } //测试泛型方法 @Test public void test4(){ Order<String> order = new Order<>(); Integer[] arr = new Integer[]{1,2,3,4}; //泛型方法在调用时,指明泛型参数的类型。 List<Integer> list = order.copyFromArrayToList(arr); System.out.println(list); }
2.注意点:
3.应用场景举例: 【DAO.java】:定义了操作数据库中的表的通用操作。 ORM思想(数据库中的表和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 public class DAO <T > { public void add (T t) { } public boolean remove (int index) { return false ; } public void update (int index,T t) { } public T getIndex (int index) { return null ; } public List<T> getForList (int index) { return null ; } public <E> E getValue () { return null ; } }
【CustomerDAO.java】: 1 2 3 4 5 6 public class CustomerDAO extends DAO <Customer > {} 【StudentDAO.java】: public class StudentDAO extends DAO <Student > {}
泛型在继承上的体现 泛型在继承上的体现: 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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 @Test public void test1 () { Object obj = null ; String str = null ; obj = str; Object[] arr1 = null ; String[] arr2 = null ; arr1 = arr2; List<Object> list1 = null ; List<String> list2 = new ArrayList<String>(); show(list1); show1(list2); } ``` public void show1 (List<String> list) { } public void show (List<Object> list) { } @Test public void test2 () { AbstractList<String> list1 = null ; List<String> list2 = null ; ArrayList<String> list3 = null ; list1 = list3; list2 = list3; List<String> list4 = new ArrayList<>(); }
通配符 1.通配符的使用 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 48 49 50 51 52 53 54 @Test public void test3 () { List<Object> list1 = null ; List<String> list2 = null ; List<?> list = null ; list = list1; list = list2; List<String> list3 = new ArrayList<>(); list3.add("AA" ); list3.add("BB" ); list3.add("CC" ); list = list3; list.add(null ); Object o = list.get(0 ); System.out.println(o); } public void print (List<?> list) { Iterator<?> iterator = list.iterator(); while (iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } }
2.涉及通配符的集合的数据的写入和读取: 见上
3.有限制条件的通配符的使用 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 48 49 50 51 52 @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()); }