Java泛型详解
目录:
1.问题现象,如何处理,新的问题
2.泛型介绍,以及注意点
3.定义泛型类
4.定义泛型方法
5.类型擦除
6.限制使用类型
1.问题现象,如何处理,新的问题
问题现象:
我们都知道在使用一个变量之前我们都需要先定义好变量的数据类型,然后再使用变量,但是如果我们需要使用一个变量它的数据类型既可以是int又可以是String...那么怎么做到呢?
我们都知道两点
1.自动装箱:基本数据类型可以自动装箱,被转换成对应的包装类;
2.向上转型:Object 是所有类的祖先类,任何一个类的实例都可以向上转型为 Object 类型,例如:
·int -->
·double -->Double --> Object
·String --> Object
那么问题得到解决:
我们将数据的类型定义为object,如下代码:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
这里的代码将XY的类型都定义为object,这样在传入数据的时候就可以实现我们之前说的问题,可以实现在变量类型未知的请况下的赋值。
但是问题来了:如何实现数据的提取与使用?
向下转型存在着风险,而且编译期间不容易发现,只有在运行期间才会抛出异常,所以要尽量避免使用向下转型。运行上面的代码,第12行会抛出 java.lang.ClassCastException 异常。
2.泛型介绍,以及注意点
定义泛型类
怎么处理?
可以使用泛型类(Java Class),它可以接受任意类型的数据。所谓“泛型”,就是“宽泛的数据类型”,任意的数据类型。
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.
首先解释一下上面的代码:
1.class
2.传值参数(我们通常所说的参数)由小括号包围,如
类型参数(泛型参数)由尖括号包围,多个参数由逗号分隔,如 或 。
3.类型参数在类后给出,在类中就可以进行使用了,类型参数标识符要使用合法的标识符,一般来说,K 表示键,V 表示值,E 表示异常或错误,T 表示一般意义上的数据类型(这个只是方便规范)。
4.泛型类在实例化的时候必须要进行给定具体的类型,也就是相当于函数中参数必须要传,格式为:
也可以省略等号右边的数据类型,但是会产生警告,即:
className variable = new className();
5.因为在使用泛型类时指明了数据类型,赋给其他类型的值会抛出异常,既不需要向下转型,也没有潜在的风险
6.·类型参数只能用来表示引用类型,不能用来表示基本类型,如
定义泛型方法:
V1 m =x;
V2 n =y;
System.out.println(“xy”+x+y);
}
需要注意到的是泛型的方法和泛型类没有什么关系
同时泛型方法的使用不用像泛型类一样要事先定义好,编译器会自动根据传入参数的类型查找出相应类型
总而言之,泛型方法除了定义上与其他方法有些不同,其他都是一样的。
类型擦除
如果在使用泛型时没有指明数据类型,那么就会擦除泛型类型
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.
如上代码在没有传入相应的类型之后再使用之后就又需要向下转型,这样的话就和我们之前最开始的代码没有区别了
限制泛型的可用类型
在上面的代码中,类型参数可以接受任意的数据类型,只要它是被定义过的。但是,很多时候我们只需要一部分数据类型就够了,用户传递其他数据类型可能会引起错误。例如,编写一个泛型函数用于返回不同类型数组(Integer 数组、Double 数组、Character 数组等)中的最大值:
1.
2.
3.
4.
5.
6.
7.
上面的代码会报错,doubleValue() 是 Number 类的方法,不是所有的类都有该方法,所以我们要限制类型参数 T,让它只能接受 Number 及其子类(Integer、Double、Character 等)。
通过 extends 关键字可以限制泛型的类型,改进上面的代码:
1.
2.
3.
4.
5.
6.
7.
表示 T 只接受 Number 及其子类,传入其他类型的数据会报错。这里的限定使用关键字