知方号

知方号

Java 泛型,你了解类型擦除吗?

转自: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 被称为参数化类型,它不是运行时真正的参数。

当然,

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。