转自:https://blog.csdn.net/briblue/article/details/76736356
很优秀的一篇文章,解决了我的疑问。
泛型,一个孤独的守门者。
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
文章开始的地方,先给大家奉上一道经典的测试题。
List l1 = new ArrayList();List l2 = new ArrayList(); System.out.println(l1.getClass() == l2.getClass());请问,上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学应该能够答出来,而对泛型有所了解,但是了解不深入的同学可能会答错。
正确答案是 true。
上面的代码中涉及到了泛型,而输出的结果缘由是类型擦除。先好好说说泛型。
泛型是什么?泛型的英文是 generics,generic 的意思是通用,而翻译成中文,泛应该意为广泛,型是类型。所以泛型就是能广泛适用的类型。
但泛型还有一种较为准确的说法就是为了参数化类型,或者说可以将类型当作参数传递给一个类或者是方法。
那么,如何解释类型参数化呢?
public class Cache { Object value; public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } }假设 Cache 能够存取任何类型的值,于是,我们可以这样使用它。
Cache cache = new Cache();cache.setValue(134);int value = (int) cache.getValue();cache.setValue("hello");String value1 = (String) cache.getValue();使用的方法也很简单,只要我们做正确的强制转换就好了。
但是,泛型却给我们带来了不一样的编程体验。
public class Cache { T value; public Object getValue() { return value; } public void setValue(T value) { this.value = value; } }这就是泛型,它将 value 这个属性的类型也参数化了,这就是所谓的参数化类型。再看它的使用方法。
Cache cache1 = new Cache();cache1.setValue("123");String value2 = cache1.getValue(); Cache cache2 = new Cache();cache2.setValue(456);int value3 = cache2.getValue();最显而易见的好处就是它不再需要对取出来的结果进行强制转换了。但,还有另外一点不同。
泛型除了可以将类型参数化外,而参数一旦确定好,如果类似不匹配,编译器就不通过。 上面代码显示,无法将一个 String 对象设置到 cache2 中,因为泛型让它只接受 Integer 的类型。
所以,综合上面信息,我们可以得到下面的结论。
与普通的 Object 代替一切类型这样简单粗暴而言,泛型使得数据的类别可以像参数一样由外部传递进来。它提供了一种扩展能力。它更符合面向抽象开发的软件编程宗旨。当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。所以说,它是一种类型安全检测机制,一定程度上提高了软件的安全性防止出现低级的失误。泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换,在定义或者实例化阶段,因为 Cache这个类型显化的效果,程序员能够一目了然猜测出代码要操作的数据类型。下面的文章,我们正常介绍泛型的相关知识。
泛型的定义和使用泛型按照使用情况可以分为 3 种。
泛型类。泛型方法。泛型接口。 泛型类我们可以这样定义一个泛型类。
public class Test { T field1;}尖括号 中的 T 被称作是类型参数,用于指代任何类型。事实上,T 只是一种习惯性写法,如果你愿意。你可以这样写。
public class Test { Hello field1;}但出于规范的目的,Java 还是建议我们用单个大写字母来代表类型参数。常见的如:
T 代表一般的任何类。E 代表 Element 的意思,或者 Exception 异常的意思。K 代表 Key 的意思。V 代表 Value 的意思,通常与 K 一起配合使用。S 代表 Subtype 的意思,文章后面部分会讲解示意。如果一个类被 的形式定义,那么它就被称为是泛型类。
那么对于泛型类怎么样使用呢?
Test test1 = new Test();Test test2 = new Test();只要在对泛型类创建实例的时候,在尖括号中赋值相应的类型便是。T 就会被替换成对应的类型,如 String 或者是 Integer。你可以相像一下,当一个泛型类被创建时,内部自动扩展成下面的代码。
public class Test { String field1;}当然,泛型类不至接受一个类型参数,它还可以这样接受多个类型参数。
public class MultiType { E value1; T value2; public E getValue1(){ return value1; } public T getValue2(){ return value2; }} 泛型方法 public class Test1 { public void testMethod(T t){ }}泛型方法与泛型类稍有不同的地方是,类型参数也就是尖括号那一部分是写在返回值前面的。中的 T 被称为类型参数,而方法中的 T 被称为参数化类型,它不是运行时真正的参数。
当然,