@
1 泛型泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
1.1 为什么需要泛型泛型是JDK1.5才出来的, 在泛型没出来之前, 我们可以看看集合框架中的类都是怎么样的。
以下为JDK1.4.2的 HashMap
可以看到, 在该版本中, 参数和返回值(引用类型)的都是 Object 对象。 而在 Java 中, 所有的类都是 Object 子类, 实用时, 可能需要进行强制类型转换。 这种转换在编译阶段并不会提示有什么错误, 因此, 在使用时, 难免会出错。
而有了泛型之后, HashMap的中使用泛型来进行类型的检查
通过泛型, 我们可以传入相同的参数又能返回相同的参数, 由编译器为我们来进行这些检查。
这样可以减少很多无关代码的书写。
因此, 泛型可以使得类型参数化, 泛型有如下的好处
类型参数化, 实现代码的复用
强制类型检查, 保证了类型安全,可以在编译时就发现代码问题, 而不是到在运行时才发现错误
不需要进行强制转换。
1.2 类型参数命名规约按照惯例,类型参数名称是单个大写字母。 通过规约, 我们可以容易区分出类型变量和普通类、接口。
E - 元素
T - 类型
N - 数字
K - 键
V - 值
S,U,V - 第2种类型, 第3种类型, 第4种类型
2 泛型的简单实用 2.1 最基本最常用最早接触的泛型, 应该就是集合框架中的泛型了。
List<Integer> list = new ArrayList<Integer>(); list.add(100086); //OK list.add("Number"); //编译错误在以上的例子中, 将 String 加入时, 会提示错误。 编译器不会编译通过, 从而保证了类型安全。
2.2 简单泛型类 2.2.1 非泛型类先来定义一个简单的类
public class SimpleClass { private Object obj; public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } }这么写是没问题的。 但是在使用上可能出现如下的错误:
public static void main(String[] args) { SimpleClass simpleClass = new SimpleClass(); simpleClass.setObj("ABC");// 传入 String 类型 Integer a = (Integer) simpleClass.getObj(); // Integer 类型接受 }以上写是不会报错的, 但是在运行时会出现报错
java.lang.ClassCastException如果是一个人使用, 那确实有可能会避免类似的情况。 但是, 如果是多人使用, 则你不能保证别人的用法是对的。 其存在着隐患。
2.2.2 泛型类的定义我们可以使用泛型来强制类型限定
public class GenericClass<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } 2.2.3 泛型类的使用在使用时, 在类的后面, 使用尖括号指明参数的类型就可以
@Test public void testGenericClass(){ GenericClass<String> genericClass = new GenericClass<>(); genericClass.setObj("AACC"); /* Integer str = genericClass.getObj();//*/ }如果类型不符, 则编译器会帮我们发现错误, 导致编译不通过。
2.3 简单泛型接口 2.3.1 定义与类相似, 以 JDK 中的 Comparable 接口为例
package java.lang; import java.util.*; public interface Comparable<T> { public int compareTo(T o); } 2.3.2 实现在实现时, 指定具体的参数类型即可。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; if (coder() == anotherString.coder()) { return isLatin1() ? StringLatin1.compareTo(v1, v2) : StringUTF16.compareTo(v1, v2); } return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) : StringUTF16.compareToLatin1(v1, v2); } ... } 2.4 简单泛型方法泛型方法可以引入自己的参数类型, 如同声明泛型类一样, 但是其类型参数我的范围只是在声明的方法本身。 静态方法和非静态方法, 以及构造函数都可以使用泛型。
2.4.1 泛型方法声明泛型方法的声明, 类型变量放在修饰符之后, 在返回值之前
public class EqualMethodClass { public static <T> boolean equals(T t1, T t2){ return t1.equals(t2); } }