美文网首页
Java泛型

Java泛型

作者: 清沐1412 | 来源:发表于2020-03-06 17:59 被阅读0次

泛型

泛型,即类型参数化,就是将原来具体的类型参数化,类似于方法中的变量参数,此时类型也被定义成了参数形式,然后在调用的时候,传入具体类型。

泛型案例:

public static void demo1(){
        ArrayList list=new ArrayList();
        list.add("kobe");
        list.add(24);
        list.add(new Object());

        for (int i=0;i<list.size();i++){
            System.out.println(list.get(i).getClass());
        }
    }

通过demo1,可以看到,list可以存任意类型。但如果创建list的时候,用泛型进行类型限定就不一样了

public static void demo2(){
        ArrayList<String> list=new ArrayList<>();   //限定String类型
        list.add(23);           //int类型,编译错误
        list.add("jordan");
        list.add("james");
        list.add(new Object()); //Object类型,编译错误
        for (String s:list) {
            System.out.println(s);
        }
    }

通过demo2,可以看到,在创建ArrayList时,指定了存储类型是String类型,所以在编译阶段存入其他类型,就会报错,只能存储String类型,由于指定了String类型,所以就可以增强for遍历。这就是泛型的本质意义所在,指定参数类型

泛型的好处

通过上面的案例,不难总结出泛型会带来的好处:

  • 编译期间就指定了类型,保证类型安全
  • 避免了强制类型转换异常
  • 编码利于重用,增加了代码的通用性

上面的好处提到了编译期间,那么运行期间呢?我通过下面的内容给大家分析。

泛型的类型擦除

泛型只在编译阶段有效,编译后程序会采取去泛型化的措施。见下面案例:

public static void demo3(){
        ArrayList list=new ArrayList();
        ArrayList<String> stringArrayList=new ArrayList<>();
        System.out.println(list.getClass()==stringArrayList.getClass());    //输出true
    }

无论有没有指定类型,都是由同一个class创建出来的,所以泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是同一个数据类型。
再看一个案例:

public static void demo4() throws Exception {
        ArrayList<String> list=new ArrayList<>();   //限定String类型
        list.add("jordan");
        list.add("james");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        Class clazz=list.getClass();
        Method add = clazz.getDeclaredMethod("add", Object.class);
        add.invoke(list,23);
        System.out.println(list.size());
    }

限定泛型类型后,通过反射进行元素新增,增加的是int类型,打印list的长度,发现+1了。因为反射是在程序运行期间,所以可以证明泛型在运行阶段被去除。

由此可见,在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦除,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

泛型的表达

无边界通配符 <?>

如果我们只有在使用的时候,才知道存入的类型时,可以使用无边界通配符来表示通用的类型

public static void demo5(ArrayList<?> arrayList){
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i));
        }
    }

main方法中:

//demo5
        ArrayList<String> arrayList=new ArrayList<>();
        arrayList.add("kobe");
        arrayList.add("bryant");
        ArrayList<Integer> arrayList1=new ArrayList<>();
        arrayList1.add(8);
        arrayList1.add(24);
        demo5(arrayList);
        demo5(arrayList1);

案例中的 ? 代表着限定通用类型. 或者这么理解,代表可变的参数类型。

上界通配符

上界通配符例如:<? extends Number>,代表限制类型为Number的子类或子孙类对象

public static void demo6(ArrayList<? extends Number> arrayList){
        for (int i = 0; i <arrayList.size(); i++) {
            System.out.println(arrayList.get(i));
        }
    }

下界通配符

下界通配符例如<? super Integer>,代表从Integer到Object所有对象都是可以的

泛型的使用

泛型跟我们的成员属性一样,使用之前要先声明,不过泛型用<>进行声明。声明一般约定采用单个大写字母表示,常用的有:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • ? - 表示不确定的java类型
  • S、U、V - 2nd、3rd、4th types

错误的使用案例:

public E get(E e){
        return null;
    }

编译器报错,为什么呢,因为泛型只有使用,没有声明
正确的案例:

public <KOBE> KOBE get(KOBE kobe){
        return null;
    }

这里声明的泛型是KOBE,故而在方法中可以使用KOBE泛型

泛型类:

泛型类一般指泛型的定义与类名一起.在创建实体对象时,指定泛型的类型

普通Car类:

public class Car {
    private String brand;

    public Car(String brand) {
        this.brand = brand;
    }

    public static void drive(){
        System.out.println("The car is driving");
    }

}

实例化过程:

Car car=new Car("benz");

加入新需求,不仅要记录品牌名称,还要记录汽车的颜色,型号等信息,这时候我们需要创建一个实体Brand进行信息的保存,此时得需求改变带来的代码代表使得我们的灵活度并不够。我们可以使用泛型类进行解决..

public class Car2<T> {
    private T brand;
    public void drive(String brand){
        System.out.println("the "+brand+" is driving");
    }

    public Car2(T brand) {
        this.brand = brand;
    }
}

Car2 实例化过程:

Brand brand=new Brand();
        brand.setColor("black");
        brand.setModel("大G");

        Car2<Brand> car2=new Car2<Brand>(brand);

通过泛型类,我们可以提升我们程序固定逻辑的灵活度

泛型方法

方法的泛型有两种:

  • 实体方法:实体方法中可以使用类中定义的泛型或者方法中定义的泛型
  • 静态方法:方法中不可用类中定义的泛型,只能用静态方法上定义的泛型
public static class demo<T,K>{
        public T method1(T t,K k){
            return (T)null;
        }

        public <S,Y>K method2(S s,Y y){
            return (K)null;
        }

        public static <J> void method3(J j){
            
        }
    }

泛型接口

指在接口的定义时进行泛型的申明.
接口是标准的指定者,指实现该接口的类必须实现其标准定义(即抽象方法).
所以在接口上进行泛型的申明,或者说使用泛型接口,可以让我们的程序代码更加简洁,更加多变.

相关文章

  • 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/axwwrhtx.html