美文网首页
java 泛型

java 泛型

作者: 扎Zn了老Fe | 来源:发表于2018-12-31 23:15 被阅读0次

泛型

在java中,像List, Map, Set等容易经常使用到,而且给我们编码带来了很大的便利,比如List<String> 我们就能够得到一个String的List容器,List<Integer> 就能够产生出一个Integer的List容器,这其中就用到了泛型。泛型就是参数化类型:

  1. 适用于多种数据类型执行相同的代码
  2. 泛型中的类型在使用时指定
  3. 泛型归根到底就是“模版”
    优点:使用泛型时,在实际使用之前类型就已经确定了,不需要强制类型转换。
    泛型既可以修饰类,也可以修饰方法和接口。这里举个例子。
public class Test1<T>{

    public  void testMethod(T t){
        System.out.println(t.getClass().getName());
    }
    public  <E> E testMethod1(E e){
        return e;
    }
  public static void main(String[] args) {
    Test1<String> t = new Test1();
    t.testMethod("generic");
    Integer i = t.testMethod1(new Integer(1));
  }
}

上面代码中,Test1<T> 是泛型类,testMethod 是泛型类中的普通方法,而 testMethod1 是一个泛型方法。而泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准。

之前写过一篇C++的模板https://www.jianshu.com/writer#/notebooks/15612794/notes/16915027,其实是同种意思,这里不再赘述。

类型擦除

先来一道有意思的题

List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();

System.out.println(l1.getClass() == l2.getClass());

  泛型是 Java 1.5 版本才引进的概念,在这之前是没有泛型的概念的,为了与以前的代码兼容,java使用了类型擦除。泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
  所以上面的题的结果是true, List<String> 和 List<Integer> 在 jvm 中的 Class 都是 List.class。类型 String 和 Integer被替换成 Object 类型。
下面将使用反射来进行验证。

package com.frank.test;
public class Erasure <T>{
    T object;

    public Erasure(T object) {
        this.object = object;
    }

}
import com.frank.test.Erasure;
public class Test {
    public static void main(String[] args) {
      Erasure<String> erasure = new Erasure<String>("hello");
      Class eclz = erasure.getClass();
      System.out.println("erasure class is:" + eclz.getName());
      Field[] fs = eclz.getDeclaredFields();
      for ( Field f : fs)  {
        System.out.println("Field name "+f.getName()+" type:"+f.getType().getName());
    }
  }
}

打印结果

erasure class is:com.frank.test.Erasure
Field name object type:java.lang.Object

通配符

类型被擦除了,就不能用父类类型来表示子类了。但是,在现实编码中,确实有这样的需求,希望泛型能够处理某一范围内的数据类型,比如某个类和它的子类,对此 Java 引入了通配符这个概念。
通配符有 3 种形式。
<?> 被称作无限定的通配符。
<? extends T> 被称作有上限的通配符。
<? super T> 被称作有下限的通配符。
<?>:只保留了所有类型的通用功能。比如下面代码

List<?> wildlist = new ArrayList<String>();
wildlist.add("123");// 编译不通过

wildlist丧失了add功能,它不管装载在这个容器内的元素是什么类型,它只关心元素的数量、容器是否为空。
<? extends T> :使用父类T来表示它的子类类型,上界<? extends T>影响写,但是不影响读。编译器只知道容器内是T或者它的派生类,但具体是什么类型不知道,而是标上一个占位符CAP#1。往容器里面写时,T的子类通常要会比父类多加方法和变量等,要比T粒度要大, 类编译器都不知道能不能和这个CAP#1匹配,所以就都不允许。

image.png
<? super T> :使用T的父类类型。下界<? super T>不影响写,但读只能放在Object对象里。因为下界规定了元素的最小粒度的下限,实际上是放松了容器元素的类型控制。既然元素是T的父类,那往里存粒度比T小的都可以。但往外读取元素就费劲了,只有所有类的基类Object对象才能装下。但这样的话,元素的类型信息就全部丢失。
image.png

参考:
[1]. https://blog.csdn.net/briblue/article/details/76736356
[2]. https://www.cnblogs.com/zhaoyibing/p/9051428.html

相关文章

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • 第二十八课:泛型

    泛型出现之前 泛型出现之后 Java深度历险(五)——Java泛型

  • Kotlin 泛型

    说起 kotlin 的泛型,就离不开 java 的泛型,首先来看下 java 的泛型,当然比较熟悉 java 泛型...

  • java泛型中类型擦除的一些思考

    java泛型 java泛型介绍 java泛型的参数只可以代表类,不能代表个别对象。由于java泛型的类型参数之实际...

  • Java泛型

    参考:Java知识点总结(Java泛型) 自定义泛型类 自定义泛型接口 非泛型类中定义泛型方法 继承泛型类 通配符...

  • Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型

    Java泛型—Java语法糖,只在编译有作用,编译后擦出泛型 在代码进入和离开的边界处,会处理泛型 Java泛型作...

  • JAVA 核心笔记 || [xxx] 泛型

    泛型 JAVA 的参数化类型 称为 泛型 泛型类的设计 Learn12.java 运行

  • 简单回顾Java泛型之-入门介绍

    什么时候开始有了Java泛型?什么是Java泛型?为什么要引入Java泛型?什么时候用到了泛型?可不可以给泛型下一...

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

  • JAVA-泛型

    JAVA-泛型 sschrodinger 2018/11/15 简介 泛型是Java SE 1.5的新特性,泛型的...

网友评论

      本文标题:java 泛型

      本文链接:https://www.haomeiwen.com/subject/dgowlqtx.html