首页 > 代码库 > Java学习笔记——泛型

Java学习笔记——泛型

一、什么是泛型?为什么要使用泛型?

且看代码:

 1 public class GenericsDemo {
 2 
 3     public static void main(String[] args) {
 4         List list = new ArrayList<>();
 5         list.add("1");
 6         list.add("2");
 7         list.add("3");
 8         list.add(5);//不小心把Integer丢进了集合中
 9         //编译不报错,运行时发生java.lang.ClassCastException异常
10         list.forEach(str -> System.out.println((String)str));
11     }
12 }

第8行代码不小心把Integer丢了进去,会引发ClassCastException

使用了泛型后:

 1 public class GenericsDemo {
 2 
 3     public static void main(String[] args) {
 4         
 5         List<String> list = new ArrayList<>();
 6         list.add("1");
 7         list.add("2");
 8         list.add(3);//不小心把Integer丢进了集合中,编译报错
 9     }
10 }

第一段代码可能引发运行时异常ClassCastException的代码,在上面代码中直接编译报错了。

 1 public class GenericsDemo {
 2 
 3     public static void main(String[] args) {
 4         
 5         List<String> list = new ArrayList<>();
 6         list.add("1");
 7         list.add("2");
 8         list.add("3");
 9         list.add("4");
10         list.forEach(str -> System.out.print(str));
11     }
12 }

发现了么,第10行不用吧str强制转换为String类型了。

1 public class GenericsDemo {
2 
3     public static void main(String[] args) {
4         Object o = new Integer(10);
5         Float f = (Float)o;
6     }
7 }

程序在编译时并不知道你到底传了什么类型的变量。由于多态(想想猫和狗的例子),程序运行的的时候可能发生类型转换异常。

为了避免ClassCastException运行时异常,Java引入泛型机制。

使用泛型的好处:

1、避免了ClassCastException

2、免去了大量的强制转换

二、定义泛型类和泛型接口

上代码:

使用泛型定义类(泛型定义接口的道理是一样的)

 1 public class Bag <T>{
 2 
 3     private T content;
 4 
 5     Bag(T content) {
 6         this.content = content;
 7     }
 8 
 9     T getContent() {
10         return content;
11     }
12 
13     void setContent(T content) {
14         this.content = content;
15     }
16 }

这里想下普通的定义方法,T是特定的类型(比如String)。这里的T可以是任意类型,类型范围很广。

1 public class TestBag {
2 
3     public static void main(String[] args) {
4         Bag<String> bag = new Bag<String>("book");
5         Integer cintent = bag.getContent();//编译出错
6         String content1 = bag.getContent();
7     }
8 }

三、使用extends关键字限定类型参数

上代码:

 1 public class LimitBag <T extends Number>{
 2 
 3     private T content;
 4 
 5     LimitBag(T content) {
 6         this.content = content;
 7     }
 8 
 9     T getContent() {
10         return content;
11     }
12 
13     void setContent(T content) {
14         this.content = content;
15     }
16 }
1 public class TestBag {
2 
3     public static void main(String[] args) {
4     
5         LimitBag<String> bag = new LimitBag<String>("book");//编译出错
6         LimitBag<Integer> bag2 = new LimitBag<Integer>(1);//合法
7     }
8 }

四、定义泛型数组

上代码:

 1 public class GenericArray<T> {
 2 
 3     private T[] content;
 4 
 5     GenericArray(T[] content) {
 6         this.content = content;
 7     }
 8 
 9     T[] getContent() {
10         return content;
11     }
12 
13     void setContent(T[] content) {
14         this.content = content;
15     }
16     
17 }

 

 1 public class TestBag {
 2 
 3     public static void main(String[] args) {
 4                 
 5         String[] content = {"1","2","3"};
 6         GenericArray<String> ss= new GenericArray<>(content);
 7         for (String item : ss.getContent()) {
 8             System.out.println(item);
 9         }
10     }
11 }

五、定义泛型方法

上代码:

 1 public class MethodTest {
 2 
 3     public static <E> void printArray(E[] arr){
 4         for (E item : arr) {
 5             System.out.println(item);
 6         }
 7     }
 8     public static <T extends Comparable<T>> T max(T x,T y){
 9         return x.compareTo(y)>0?x:y;
10     }
11     public static void main(String[] args) {
12         Integer[] arr = {1,2,3};//必须是包装类
13         printArray(arr);
14         System.out.println(max("B", "a"));
15     }
16     
17 }

 六、问号通配符

上代码

1 public class WildCast {
2 
3     public static void main(String[] args) {
4         Set<String> set = new HashSet<String>();//向上转型
5         //HashSet<Object> set = new HashSet<String>();//编译出错Type mismatch,泛型Object和泛型String之间不存在继承关系
6     }
7 }

 在看下面代码:

 1 public class WildCast {
 2 
 3     public static void main(String[] args) {
 4         
 5         List<Integer> list = new ArrayList<>();
 6         list.add(11);
 7         print(list);//编译出错
 8         printNew(list);
 9     }
10 
11     private static void printNew(Collection<?> collection) {
12         // TODO Auto-generated method stub
13         collection.forEach(obj -> System.out.println(obj));
14     }
15 
16     private static void print(Collection<Object> collection) {
17         // TODO Auto-generated method stub
18         collection.forEach(obj -> System.out.println(obj));
19     }
20 }

泛型<Integer>和泛型<Object>没有继承关系,不能传递。所以使用通配符<?>

Java学习笔记——泛型