二、JavaSE_集合(泛型)

泛型

一、泛型的概述

1.初步了解

首先,我们来看什么是泛型?

1 List list = new ArrayList();                        //没有泛型约束
2 List<String> list = new ArrayList<String>();//有泛型约束                                    
View Code

第一行代码,没有进行泛型约束,也就是list可以存储的类型是Object。那么这样会存在安全隐患,接下来,我们会谈谈安全隐患的问题。

第二行代码,就是有泛型进行约束的,也就是说第二个list当中只能存放String类型的数据。注:jdk1.7以后,也可以这样定义:List<String> list = new ArrayList<>();也就是后面的类型可以不写。

我们来看Collection的API

E代表的是元素(Element)

其中那个E就代表泛型。

2.泛型的好处

  •  提高了安全性(将运行期的错误转换到编译期
  • 省去强转的麻烦

3.泛型解决安全隐患

安全隐患的问题,通过代码来看:

 1 /**
 2  * 早期的Object类型可以接收任意的对象类型,
 3  * 但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
 4  */
 5 public class Demo {
 6     public static void main(String[] args){
 7         //创建工具类对象
 8         Tool tool = new Tool();
 9         //往工具类设置狗类
10         tool.setObject(new Dog("金毛","金黄色"));
11         //获取猫对象
12         Cat cat = (Cat) tool.getObject();
13     }
14 }
15 
16 
17 //工具类
18 class Tool {
19     private Object object;
20 
21     public Object getObject() {
22         return object;
23     }
24 
25     public void setObject(Object object) {
26         this.object = object;
27     }
28 }
29 
30 //动物类
31 class Animal {
32     private String name;
33     private String color;
34 
35     public Animal() {
36     }
37 
38     public Animal(String name, String color) {
39         this.name = name;
40         this.color = color;
41     }
42 
43     public String getName() {
44         return name;
45     }
46 
47     public void setName(String name) {
48         this.name = name;
49     }
50 
51     public String getColor() {
52         return color;
53     }
54 
55     public void setColor(String color) {
56         this.color = color;
57     }
58 
59     @Override
60     public String toString() {
61         return "Animal{" +
62                 "name='" + name + '\'' +
63                 ", color='" + color + '\'' +
64                 '}';
65     }
66 }
67 
68 //狗类
69 class Dog extends Animal {
70 
71     public Dog() {
72     }
73 
74     public Dog(String name, String color) {
75         super(name, color);
76     }
77 }
78 
79 //猫类
80 class Cat extends  Animal {
81     public Cat() {
82     }
83 
84     public Cat(String name, String color) {
85         super(name, color);
86     }
87 }
View Code

我们来看这段代码,工具类Tool,他是可以设置任意对象的,即Object,那么Cat和Dog都是继承Animal类,当往工具类设置Dog类时,Tool是可以接收的,获取时也可以强转成Cat类时编译也是可以的,但是运行时:

java.lang.ClassCastException类型转换异常,因此在这里如果没使用泛型就会导致在运行时存在类型转换异常,因此会出现安全隐患。

那么,加了泛型之后呢?请看代码:(将Tool加上泛型)

 1 //工具类
 2 class Tool<T> {
 3     private T object;
 4 
 5     public T getObject() {
 6         return object;
 7     }
 8 
 9     public void setObject(T object) {
10         this.object = object;
11     }
12 }

加上泛型之后,等于约束了Tool能存放的类型,一旦存放的不是该类型,那么就直接在编译期间就提示错误,这也就是为什么泛型将运行期的错误转移到编译期了

 

 二、泛型方法的使用
1.成员方法的泛型

 泛型方法(扑通)也就是把泛型定义在方法上,定义格式:

public <泛型类型> 返回类型 方法名(泛型类型 变量名)

    public<T> void move(T t) {      //方法类型最好与类方形一致
        System.out.println(t);      //如果不一致,那么要在方法上声明类型
    }

 完整版:

 1 public class Demo {
 2     public static void main(String[] args){
 3         //创建工具类对象
 4         Tool<Dog> tool = new Tool<>();
 5         tool.move(new Dog("泰迪","屎黄色"));
 6         tool.move(new Cat("旺财","黄色"));
 7     }
 8 }
 9 
10 
11 //工具类
12 class Tool<T> {
13     private T object;
14 
15     public T getObject() {
16         return object;
17     }
18 
19     public void setObject(T object) {
20         this.object = object;
21     }
22 
23     //成员方法
24     public<T> void move(T t) {      //方法类型最好与类方形一致
25         System.out.println(t);      //如果不一致,那么要在方法上声明类型
26     }
27 
28 }
29 
30 //动物类
31 class Animal {
32     private String name;
33     private String color;
34 
35     public Animal() {
36     }
37 
38     public Animal(String name, String color) {
39         this.name = name;
40         this.color = color;
41     }
42 
43     public String getName() {
44         return name;
45     }
46 
47     public void setName(String name) {
48         this.name = name;
49     }
50 
51     public String getColor() {
52         return color;
53     }
54 
55     public void setColor(String color) {
56         this.color = color;
57     }
58 
59     @Override
60     public String toString() {
61         return "Animal{" +
62                 "name='" + name + '\'' +
63                 ", color='" + color + '\'' +
64                 '}';
65     }
66 }
67 
68 //狗类
69 class Dog extends Animal {
70 
71     public Dog() {
72     }
73 
74     public Dog(String name, String color) {
75         super(name, color);
76     }
77 }
78 
79 //猫类
80 class Cat extends  Animal {
81     public Cat() {
82     }
83 
84     public Cat(String name, String color) {
85         super(name, color);
86     }
87 }
View Code

结果:

2.静态方法的泛型

 定义格式:public static <泛型类型> 返回类型 方法名(泛型类型 变量名)

 

//静态成员方法泛型
public static<Q> void show(Q q){  //静态方法必须声明自己的泛型
        System.out.println(q);
}

 

为什么要声明自己的泛型,这是因为调用move方法是在创建对象以后调用,而静态方法是类加载就可以调用,他们的生命周期不一样。

看代码:

 1 public class Demo {
 2     public static void main(String[] args){
 3         //创建工具类对象
 4         Tool<Dog> tool = new Tool<>();
 5         tool.move(new Dog("泰迪","屎黄色"));
 6         Tool.show(new Cat("旺财","黄色"));
 7     }
 8 }
 9 
10 
11 //工具类
12 class Tool<T> {
13     private T object;
14 
15     public T getObject() {
16         return object;
17     }
18 
19     public void setObject(T object) {
20         this.object = object;
21     }
22 
23     //成员方法
24     public<T> void move(T t) {      //方法类型最好与类方形一致
25         System.out.println(t);      //如果不一致,那么要在方法上声明类型
26     }
27 
28     //静态成员方法泛型
29     public static<Q> void show(Q q){  //静态方法必须声明自己的泛型
30         System.out.println(q);
31     }
32 
33 }
34 
35 //动物类
36 class Animal {
37     private String name;
38     private String color;
39 
40     public Animal() {
41     }
42 
43     public Animal(String name, String color) {
44         this.name = name;
45         this.color = color;
46     }
47 
48     public String getName() {
49         return name;
50     }
51 
52     public void setName(String name) {
53         this.name = name;
54     }
55 
56     public String getColor() {
57         return color;
58     }
59 
60     public void setColor(String color) {
61         this.color = color;
62     }
63 
64     @Override
65     public String toString() {
66         return "Animal{" +
67                 "name='" + name + '\'' +
68                 ", color='" + color + '\'' +
69                 '}';
70     }
71 }
72 
73 //狗类
74 class Dog extends Animal {
75 
76     public Dog() {
77     }
78 
79     public Dog(String name, String color) {
80         super(name, color);
81     }
82 }
83 
84 //猫类
85 class Cat extends  Animal {
86     public Cat() {
87     }
88 
89     public Cat(String name, String color) {
90         super(name, color);
91     }
92 }
View Code

注意这个:

 

结果:

 

 当通过类名.方法名时,那么还没有创建对象,不会让你去约束泛型,因此必须在静态方法上加上自己的泛型。

 

三、泛型接口的概述和使用

 1.概述

泛型接口,也就是在接口上定义泛型。

2.定义格式:

public interface 接口名<泛型类型>

如:

//接口泛型
interface Inter<String>{
    void method(String str);
}

 Code:

 1 public class Test_Generic {
 2     public static void main(String[] args){
 3         Inter inter = new ImplInter();
 4         inter.method("唐豆豆,你个迷人的小妖精");
 5     }
 6 }
 7 //接口泛型
 8 interface Inter<String>{
 9     void method(String str);
10 }
11 //实现接口重写方法
12 class ImplInter implements Inter<String>{
13 
14     @Override
15     public void method(String str) {
16         System.out.println(str);
17     }
18 }
View Code

结果:

 

泛型后面还有一点会再说,将集合复习完毕之时,再补充一点关于泛型的通配符,仅作了解。

 

如有错误之处,欢迎指正。

邮箱:it_chang@126.com

posted @ 2018-03-30 17:04  changDV  阅读(250)  评论(0编辑  收藏  举报