说起KTV恐怕没几个人不知道的。虽然这玩意没有过去那么火热了,但喝了酒之后再去飙几个高八度的爆破音还是蛮爽的。
但Java里面也有一个基础特性用到了KTV——泛型。
泛型,它的作用就是字面意思:宽泛的类型。怎么个宽泛法呢?
在没有泛型时,假设李雷写了一句这样的代码:
List list = new ArrayList();
这句代码,除了李雷之外,谁都不能一眼看出list中保存的到底是哪种数据类型。
那么当你接手这样的代码时,就只能在8种基本数据类型、8种封装类型和String类型之间挨个试,并且这还只是一行代码哦。如果项目稍大一些,可能会有上百行这样的代码哦~
你这时心里头肯定有一万头XXX跑过。
这种情况,也被Java的缔造者们注意到了,这毕竟是他们自己遗留下来的「Bad Smell」。
于是,他们在JDK 1.5中加入了这个叫「泛型」的东西,也就是说不仅数据本身是参数,数据类型也可以被指定为参数(这话有点轴,先不管它)。它的目的就是要使代码能够应用于「使用的时候不知道是什么类型」的场景。
举个例子:
public class User<K> {private K name;
public K getName() {
return name;
}
public void setName(K name) {
this.name = name;
}
public static void main(String[] args) {
User user1 = new User();
user1.setName("xiangwang");
System.out.println(user1.getName() instanceof String);
User user2 = new User();
user2.setName(123456);
System.out.println(user2.getName() instanceof Integer);
User user3 = new User();
user3.setName(123.456);
System.out.println(user3.getName() instanceof Double);
User user4 = new User();
System.out.println(user4.getName() instanceof Double);
}
}
由于在getName()之前调用过setName(),所以当判断设置的类型是否是字符串、整数和浮点时,user1、user2和user3的结果就自然会是true。而user4的name属性字段事先没有设置任何值,所以Java也无法判断读出来的究竟是什么,结果自然就是true。
说了这么多,「泛型」长成这样:
或者这样:
本质上K、T、V、E、?这些字母没什么区别,只不过是编码时一种约定俗成的东西。比如T ,可以换成A-Z之间任何一个字母。通常情况下,K、T、V、E、?是这样约定的:
- K/V(key/value)分别代表键值对中的键和值;
- T(type)表示具体的类型;
- E(element)代表Element;
- ?表示不确定的类型;
还是拿刚才的例子说:
List<String> list = new ArrayList<String>();
如果李雷交给你这样的代码,那么你就可以知道,他在list列表里存放的都是String类型,所以,你就可以放心大胆地存取String类型的数据了,绝不会报错,这个Java可以向你保证。