为什么要使用泛型?
未使用泛型的情况:
// 创建列表类 List list = new ArrayList(); // 添加一个类型为 String 的列表元素 list.add("hello"); // 强制转换为 String 类型,再赋值给类型为 s 的引用变量 String s = (String) list.get(0);使用泛型的情况:
// 创建泛型类,<String> 为类型参数 List<String> list = new ArrayList<String>(); // 添加一个类型为 String 的列表元素 list.add("hello"); // 这里不需要强制类型转换 String s = list.get(0);好处:实现通用的泛型算法,处理不同类型的集合,可以自定义类型,类型安全,便于阅读。
泛型类型一个泛型类型是一个类型参数化(<类型参数>)的泛型类或接口。
一个简单的 Box 类 public class Box { private Object object; public void set(Object object) { this.object = object; } public Object get() { return object; } }Box 类中方法接受或返回一个对象,除了基本类型外你可以传入任何对象。编译时无法检查类是如何使用的,如果传入一个 Integer 并希望获取 Integer,但却错误传入 String 对象,那么就会导致运行错误。
泛型版本 Box 类泛型类型定义格式:
class name<T1, T2, ..., Tn> { /* ... */ } //T1, T2, ..., Tn为类型参数类型参数(也成为类型变量)跟在类名称后面,类型参数放在尖括号(<>)中(T1, T2, ..., and Tn),
修改后的泛型 Box 类:
/** * Box 类的泛型版本 * @param <T> 类型的值被装箱 */ public class Box<T> { // T 表示 "类型" private T t; public void set(T t) { this.t = t; } public T get() { return t; } }上面代码中,Box 类中的所有 Object 类型都被替换为 T 类型,类型变量可以是指定的任何非基本类型:任何类类型、任何接口类型、任何数组类型,甚至是任何其他的类型变量。
泛型技术也可以实现通用的泛型接口。
类型参数的命名约定按照惯例,类型参数名为单个大写字母。这与已知的变量命名约定形成鲜明对比,这样做有充分的理由:如果没有这个约定,那么很难区分类型变量和普通类或接口名称之间的区别。
最常用的类型参数名称:
调用和实例化泛型类型用具体的类型替换类型变量 T 就可以实例化泛型类型,例如:
Box <Integer> integerBox = new Box <Integer>();通用类型的调用一般称为“参数化类型”。
像往常一样使用new关键字实例化,但在类名和括号之间放置<Integer>:
在 Java SE 7 和更高的版本中,只要编译器可以根据上下文确定或推断类型参数,就可以用一组空类型参数(<>)替换调用泛型类的构造函数所需的类型参数。例如:
Box<Integer> integerBox = new Box<>(); 多类型参数泛型类可以拥有多个类型参数。例如,实现通用 Pair 接口的通用 OrderedPair 类:
public interface Pair<K, V> { public K getKey(); public V getValue(); } public class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } }以下语句创建 OrderedPair 类的两个实例:
Pair <String,Integer> p1 = new OrderedPair <String,Integer>(“Even”,8); Pair <String,String> p2 = new OrderedPair <String,String>(“hello”,“world”);新的OrderedPair <String,Integer>代码将 K 实例化为一个字符串,将 V 实例化为一个整数。因此,OrderedPair 的构造函数的参数类型分别是 String 和 Integer。由于自动装箱,将 String 和 int 传递给类是有效的。