Java - 泛型(1)
为什么要使用泛型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 功能:泛型的使用,解释为什么使用泛型 3 */ 4 package generic; 5 6 import java.util.ArrayList; 7 import java.util.Iterator; 8 9 public class GenericTest01 10 { 11 public static void main(String[] args) 12 { 13 genericDemo(); 14 // genericDemo2(); 15 } 16 17 // 没有使用泛型 18 public static void genericDemo() 19 { 20 ArrayList al = new ArrayList(); 21 al.add("qwe"); 22 // 上面添加的字符串,下面添加的是int,迭代时肯定会报类型转换异常 23 al.add(4); 24 25 Iterator it = al.iterator(); 26 while(it.hasNext()) 27 { 28 // 需要强制类型转换 29 // 此处在运行时会报类型转换异常:ClassCastException 30 // 在编译时不会报异常 31 String s = (String)it.next(); // 1 32 System.out.println(s + ":" + s.length()); 33 } 34 35 /** 36 * 当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,该对象的编译类型变成了Object类型, 37 * 但其运行时类型任然为其本身类型; 38 * 因此,//1 处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现"java.lang.ClassCastException"异常; 39 */ 40 } 41 42 // JDK1.5之后使用泛型 43 // 解决安全问题 44 public static void genericDemo2() 45 { 46 // 指定只添加String类型数据 47 ArrayList<String> al = new ArrayList<String>(); 48 al.add("qwe"); 49 // 编译时下面这条语句就报错了 50 // al.add(4); 51 52 // 迭代器也通过泛型指定类型 53 // 后续就不需要强制类型转换了 54 Iterator<String> it = al.iterator(); 55 while(it.hasNext()) 56 { 57 String s = it.next(); 58 System.out.println(s + ":" + s.length()); 59 } 60 } 61 }
什么是泛型:
自定义泛型类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 自定义泛型类 3 */ 4 package generic; 5 6 // 用于测试效果 7 public class GenericTest02 8 { 9 public static void main(String[] args) 10 { 11 Tool tool = new Tool(); 12 tool.setObject(new Teacher()); 13 // 没用泛型之前,编译器提示必需要进行强制类型转换 14 Teacher teacher = (Teacher) tool.getObject(); 15 System.out.println(teacher); 16 17 Util<Doctor> util = new Util<Doctor>(); 18 util.setObject(new Doctor()); 19 // 使用泛型之后,不需要进行强转 20 Doctor doctor = util.getObject(); 21 System.out.println(doctor); 22 } 23 } 24 25 // 没有使用泛型 26 class Tool 27 { 28 private Object object; 29 30 public Object getObject() 31 { 32 return object; 33 } 34 35 public void setObject(Object object) 36 { 37 this.object = object; 38 } 39 } 40 41 // 使用泛型,自定义泛型类 42 class Util<Q> 43 { 44 private Q object; 45 46 public void setObject(Q q) 47 { 48 this.object = q; 49 } 50 public Q getObject() 51 { 52 return object; 53 } 54 } 55 56 class Doctor 57 { 58 59 } 60 61 class Teacher 62 { 63 64 }
方法上定义泛型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 方法上定义泛型 3 */ 4 package generic; 5 6 // 用于测试效果 7 public class GenericTest03 8 { 9 public static void main(String[] args) 10 { 11 Utils ut = new Utils(); 12 // 可以打印字符串 13 ut.show("qwe"); 14 // 可以打印int类型 15 ut.show(12); 16 } 17 } 18 19 // 方法上定义泛型 20 class Utils 21 { 22 // 语法格式必须如下所示 23 public <T> void show(T t) 24 { 25 System.out.println("show:" + t); 26 } 27 28 // 下面两种书写方式都是错的 29 // public void show(T t) 30 // public <T> void show(String str) 31 32 public <Q> void print(Q q) 33 { 34 System.out.println("print:" + q); 35 } 36 37 // 泛型字母可以任意定义,不用区分大小写 38 public <Y> void print2(Y y) 39 { 40 System.out.println("print:" + y); 41 } 42 }
类和方法上都定义泛型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 类和方法上都定义泛型 3 */ 4 package generic; 5 6 // 用于测试效果 7 public class GenericTest04 8 { 9 public static void main(String[] args) 10 { 11 Tools<String> tl = new Tools<String>(); 12 // 只能打印String类型 13 tl.show("qwer"); 14 // 打印其他类型报错 15 // tl.show(123); 16 17 // 可以打印String类型 18 tl.print("qwe"); 19 // 也可以打印其他类型 20 tl.print(123); 21 22 // 可以打印String类型 23 tl.print2("qwer"); 24 // 也可以打印其他类型 25 tl.print2(123); 26 27 Tools.display("qwe"); 28 Tools.display(123); 29 } 30 } 31 32 // 类和方法上都定义泛型 33 class Tools<T> 34 { 35 // 这个方法的类型是跟着对象(类型T)走的,Q不起作用 36 public <Q> void show(T t) 37 { 38 System.out.println("show:" + t); 39 } 40 41 // 这个方法的类型是跟着Q走的 42 public <Q> void print(Q q) 43 { 44 System.out.println("print:" + q); 45 } 46 47 @SuppressWarnings("hiding") 48 public <T> void print2(T q) 49 { 50 System.out.println("print2:" + q); 51 } 52 53 // 泛型定义在返回值的前面,修饰符的后面 54 public static <W> void display(W w) 55 { 56 System.out.println("display:" + w); 57 } 58 }
接口上定义泛型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 接口上定义泛型 3 */ 4 package generic; 5 6 // 用于测试效果 7 public class GenericTest05 8 { 9 public static void main(String[] args) 10 { 11 InterImpl01 ii = new InterImpl01(); 12 ii.show("qwe"); 13 // ii.show(123); 编译时报错 14 15 InterImpl02<String> ii2 = new InterImpl02<String>(); 16 ii2.show("asd"); 17 // ii2.show(123); 编译时报错 18 19 InterImpl02<Integer> ii3 = new InterImpl02<Integer>(); 20 ii3.show(123); 21 // ii3.show("asd"); 编译时报错 22 } 23 } 24 25 // 接口上定义泛型 26 interface Inter<T> 27 { 28 public void show(T t); 29 } 30 31 // T是具体的数据类型,在实现类后面不需要加上 <String> 32 class InterImpl01 implements Inter<String> 33 { 34 @Override 35 public void show(String t) 36 { 37 System.out.println("show:" + t); 38 } 39 } 40 41 // T如果不是具体的数据类型的话,实现类和接口后面都要加上<T> 42 class InterImpl02<T> implements Inter<T> 43 { 44 @Override 45 public void show(T t) 46 { 47 System.out.println("show:" + t); 48 } 49 }
泛型的高级特性:
高级特性01:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 功能:泛型的高级特性01 3 */ 4 package generic.generic05; 5 6 import java.util.ArrayList; 7 import java.util.Iterator; 8 9 public class GenericTest01 10 { 11 public static void main(String[] args) 12 { 13 ArrayList<String> al1 = new ArrayList<String>(); 14 al1.add("qwe"); 15 al1.add("asd"); 16 al1.add("zxc"); 17 18 ArrayList<Integer> al2 = new ArrayList<Integer>(); 19 al2.add(123); 20 al2.add(456); 21 al2.add(789); 22 23 // demo(al1); 24 // demo(al2); 25 26 demo2(al1); 27 // demo2(al2); 28 } 29 30 // 不清楚是什么类型时候,可以用?代替 31 public static void demo(ArrayList<?> al) 32 { 33 Iterator<?> it = al.iterator(); 34 while(it.hasNext()) 35 { 36 System.out.println("al:" + it.next()); 37 // 以下使用length()是错误的 38 // 因为不知道是什么类型,所以不能使用某一具体类型的特有方法 39 // System.out.println(it.next().length()); 40 } 41 } 42 43 // 也可以换成T,但T代表了某一个具体类型,比如String,不是真让你写一个T在里面,其实是写一个具体类型 44 // 操作方面有一点变化 45 public static <T> void demo2(ArrayList<T> al) 46 { 47 Iterator<T> it = al.iterator(); 48 while(it.hasNext()) 49 { 50 System.out.println("al:" + it.next()); 51 // 使用了某一具体类型之后 52 // 可以用这个具体类型来接收迭代出来的元素,并进行其他具体操作 53 /*T t = it.next(); 54 System.out.println("al:" + t);*/ 55 } 56 } 57 }
高级特性02:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 功能:泛型的高级特性02 3 */ 4 package generic; 5 6 import java.util.ArrayList; 7 import java.util.Iterator; 8 9 public class GenericTest07 10 { 11 public static void main(String[] args) 12 { 13 ArrayList<Person> al = new ArrayList<Person>(); 14 al.add(new Person("qwe")); 15 al.add(new Person("asd")); 16 al.add(new Person("zxc")); 17 18 ArrayList<Worker> al2 = new ArrayList<Worker>(); 19 al2.add(new Worker("qwe")); 20 al2.add(new Worker("asd")); 21 al2.add(new Worker("zxc")); 22 23 ArrayList<Student> al3 = new ArrayList<Student>(); 24 al3.add(new Student("qwe")); 25 al3.add(new Student("asd")); 26 al3.add(new Student("zxc")); 27 28 // 正确 29 demo(al); 30 // 以下两种写法错误,是不允许的,左右不匹配 31 // ArrayList<Person> al2 = new ArrayList<Student>(); 32 // ArrayList<Student> al2 = new ArrayList<Person>(); 33 // demo(al2); // 错误,只能打印 ArrayList<Person> 类型数据 34 // demo(al3); // 错误,只能打印 ArrayList<Person> 类型数据 35 36 demo2(al); 37 demo2(al2); 38 demo2(al3); 39 40 demo3(al2); 41 demo3(al); 42 // Student类不是Person类的子类,所以下面写法错误 43 // demo3(al3); 44 45 demo4(al); 46 demo4(al2); 47 // Student类不是Worker类的父类,所以下面写法错误 48 // demo4(al3); 49 } 50 51 // 打印出特定类型 52 public static void demo(ArrayList<Person> al) 53 { 54 Iterator<Person> it = al.iterator(); 55 while(it.hasNext()) 56 { 57 Person p = it.next(); 58 System.out.println("name:" + p.getName()); 59 } 60 } 61 62 // 打印出所有类型 63 public static void demo2(ArrayList<?> al) 64 { 65 Iterator<?> it = al.iterator(); 66 while(it.hasNext()) 67 { 68 System.out.println(it.next()); 69 } 70 } 71 72 // 打印出指定的范围类型:泛型限定 73 // 只打印Person和它的子类 74 public static void demo3(ArrayList<? extends Person> al) 75 { 76 Iterator<? extends Person> it = al.iterator(); 77 while(it.hasNext()) 78 { 79 // 可以调用具体方法 80 System.out.println(it.next().getName()); 81 } 82 } 83 84 // 打印出指定的范围类型:泛型限定 85 // 只打印Worker和它的父类(是Worker类的基类) 86 public static void demo4(ArrayList<? super Worker> al) 87 { 88 Iterator<? super Worker> it = al.iterator(); 89 while(it.hasNext()) 90 { 91 System.out.println(it.next()); 92 } 93 } 94 } 95 96 class Person 97 { 98 private String name; 99 100 public Person(String name) 101 { 102 this.name = name; 103 } 104 105 public String getName() 106 { 107 return name; 108 } 109 public void setName(String name) 110 { 111 this.name = name; 112 } 113 } 114 115 class Student 116 { 117 private String name; 118 119 public Student(String name) 120 { 121 this.name = name; 122 } 123 124 public String getName() 125 { 126 return name; 127 } 128 public void setName(String name) 129 { 130 this.name = name; 131 } 132 } 133 134 class Worker extends Person 135 { 136 public Worker(String name) 137 { 138 super(name); 139 } 140 }
高级特性03:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 未使用高级特性之前 3 */ 4 package generic; 5 6 import java.util.Comparator; 7 import java.util.Iterator; 8 import java.util.TreeSet; 9 10 public class GenericTest08_1 11 { 12 public static void main(String[] args) 13 { 14 // 使用Studnet类的构造器 15 TreeSet<Student1> tr = new TreeSet<Student1>(new StuComparator()); 16 tr.add(new Student1("stu4")); 17 tr.add(new Student1("stu2")); 18 tr.add(new Student1("stu3")); 19 20 Iterator<Student1> it = tr.iterator(); 21 while(it.hasNext()) 22 { 23 System.out.println("tr:" + it.next().getName()); 24 } 25 26 // 使用Worker类的构造器 27 TreeSet<Worker1> tr2 = new TreeSet<Worker1>(new WorComparator()); 28 tr2.add(new Worker1("wor1")); 29 tr2.add(new Worker1("wor5")); 30 tr2.add(new Worker1("wor3")); 31 32 Iterator<Worker1> it2 = tr2.iterator(); 33 while(it2.hasNext()) 34 { 35 System.out.println("tr:" + it2.next().getName()); 36 } 37 } 38 } 39 40 class MyComparator implements Comparator<Person1> 41 { 42 @Override 43 public int compare(Person1 o1, Person1 o2) 44 { 45 return o1.getName().compareTo(o2.getName()); 46 } 47 } 48 49 // Student类的比较器,分开写很麻烦 50 class StuComparator implements Comparator<Student1> 51 { 52 @Override 53 public int compare(Student1 o1, Student1 o2) 54 { 55 return o1.getName().compareTo(o2.getName()); 56 } 57 } 58 59 // Worker类的比较器,分开写很麻烦 60 class WorComparator implements Comparator<Worker1> 61 { 62 @Override 63 public int compare(Worker1 o1, Worker1 o2) 64 { 65 return o1.getName().compareTo(o2.getName()); 66 } 67 } 68 69 class Person1 70 { 71 private String name; 72 73 public Person1(String name) 74 { 75 this.name = name; 76 } 77 78 public String getName() 79 { 80 return name; 81 } 82 public void setName(String name) 83 { 84 this.name = name; 85 } 86 } 87 88 class Student1 extends Person1 89 { 90 // private String name; 91 public Student1(String name) 92 { 93 super(name); 94 } 95 } 96 97 class Worker1 extends Person1 98 { 99 public Worker1(String name) 100 { 101 super(name); 102 } 103 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 * 使用高级特性之后 3 */ 4 package generic; 5 6 import java.util.Comparator; 7 import java.util.Iterator; 8 import java.util.TreeSet; 9 10 public class GenericTest08_2 11 { 12 public static void main(String[] args) 13 { 14 // 使用通用的比较器(父类的比较器) 15 TreeSet<Student2> tr = new TreeSet<Student2>(new MyComparator2()); 16 tr.add(new Student2("stu4")); 17 tr.add(new Student2("stu2")); 18 tr.add(new Student2("stu3")); 19 20 Iterator<Student2> it = tr.iterator(); 21 while(it.hasNext()) 22 { 23 System.out.println("tr:" + it.next().getName()); 24 } 25 26 // 使用通用的比较器(父类的比较器) 27 TreeSet<Worker2> tr2 = new TreeSet<Worker2>(new MyComparator2()); 28 tr2.add(new Worker2("wor1")); 29 tr2.add(new Worker2("wor5")); 30 tr2.add(new Worker2("wor3")); 31 32 Iterator<Worker2> it2 = tr2.iterator(); 33 while(it2.hasNext()) 34 { 35 System.out.println("tr:" + it2.next().getName()); 36 } 37 } 38 } 39 40 class MyComparator2 implements Comparator<Person2> 41 { 42 @Override 43 public int compare(Person2 o1, Person2 o2) 44 { 45 return o1.getName().compareTo(o2.getName()); 46 } 47 } 48 49 class Person2 50 { 51 private String name; 52 53 public Person2(String name) 54 { 55 this.name = name; 56 } 57 58 public String getName() 59 { 60 return name; 61 } 62 public void setName(String name) 63 { 64 this.name = name; 65 } 66 } 67 68 class Student2 extends Person2 69 { 70 // private String name; 71 public Student2(String name) 72 { 73 super(name); 74 } 75 } 76 77 class Worker2 extends Person2 78 { 79 public Worker2(String name) 80 { 81 super(name); 82 } 83 }