Java 泛型
泛型:宽泛的数据类型
一、泛型概念
Java在1.5之后加入了泛型的概念。泛型,即“参数化类型”。泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
先举例:
ArrayList<String> list1=new ArrayList<String>(); //list1.add(520);//编译报错
ArrayList容器可以存放任何类型,但是list1指定了String类型,则需要以String型使用。为了解决类似这样的问题(在编译阶段就可以解决),泛型应运而生。
ArrayList<String> list1=new ArrayList<String>(); ArrayList<Integer> list2=new ArrayList<Integer>(); //list1.add("守林鸟"); //list1.add(520);//编译报错 Class class1=list1.getClass(); Class class2=list2.getClass(); if(class1==class2) System.out.println("泛型测试,类型相同");//表示这是同一类型的对象
对于编译器来说,list1和list2是同一类型的对象,因为编译之后采取了类似于去泛型化的措施,也就是泛型的类型擦除。
二、为什么要设计泛型
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况 ,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处:使用泛型,首先可以通过IDE进行代码类型初步检查,然后在编译阶段进行编译类型检查,以保证类型转换的安全性;并且所有的强制转换都是自动和隐式的,可以提高代码的重用率。
三、泛型的基本使用(一般用大写字母T,S等,不支持基本类型)
- 泛型类:class 类名<泛型标识符T>{}
- 泛型属性:和泛型类一起使用
- 泛型方法:[作用域修饰符] <泛型类型标识T> [返回类型] 方法名称(参数列表){};用泛型标识符把原本的类型替代掉,在方法的返回值类型、传参类型里。不是泛型类也可以有泛型方法,泛型方法与泛型类没有必然的联系。
- 泛型接口:interface 接口名<泛型标识符>;实现接口的类也需要生命泛型。如果传入实参类型(即把T改成具体类如String),则实现接口里所有方法的过程中,都需要把T改成String。
例如:知道某个人的信息,有时候需要传入int型的生日,有时候需要传入String型的姓名,不用泛型需要写2个类,用不同类型标识属性,泛型可以实现代码复用。
//测试泛型 public class TestF{ public static void main(String[] args) { Person p1=new Person(19981102); Person p2=new Person("守林鸟"); Person p3=new Person(520.1314); System.out.println(p1); System.out.println(p2); System.out.println(p3); p1.walk("博客园"); p1.walk(10086); Man man=new Man(); man.eat("鸭子"); man.eat(1314); Super_Dog sDog=new Super_Dog(); sDog.jiao(10022222); sDog.jiao("霸王别鸡"); } } class Person<T>{ private T message; public Person(T message) { this.message=message; } public String toString() { return "这个人的信息是"+this.message; } public <S> void walk(S type) {//这里的S和T不冲突,因为方法可以独立使用泛型 System.out.println("这里调用了walk方法,type="+type); } } interface Human<S>{ public S eat(S food); } class Man<S> implements Human<S>{//实现类Man也需要声明泛型 public S eat(S food) { System.out.println("food="+food); return food; } } class Super_Dog{ public <P> void jiao(P p) {//类没有泛型,方法有泛型 System.out.println("P="+p); } }
输出:
这个人的信息是19981102
这个人的信息是守林鸟
这个人的信息是520.1314
这里调用了walk方法,type=博客园
这里调用了walk方法,type=10086
food=鸭子
food=1314
P=10022222
P=霸王别鸡
还有通配符和边界的知识点,翻了很多博客都看不懂,先放着吧,感觉短时间内也用不上。。。