Java 泛型

导读:本篇文章讲解 Java 泛型,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Java 泛型(generics)是 JDK 5 中引入的一个新特性.

泛型提供了编译时类型安全检测机制,好处是能够在编译的时候就检查类型安全.

使用Object可以接收任意类型的参数,但是存在类型转换的问题.泛型可以解决它.

泛型的参数只能是引用类型(类)

泛型的类型参数可以有多个

没有定义具体类型,默认为Object

泛型回顾

在学习JavaSE中的集合Collection时,以及自定义数组/链表/二叉树的元素类型时使用过泛型

集合中

//ArrayList源码  
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
 transient Object[] elementData; // Object类型数组,可以接收任何引用类型
ArrayList<Integer> list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList();

自定义类中

public class MyselfArray<T> {
	//数组当前元素个数
    private int size;

    //泛型数组
    private T[] data;
    
    //构造方法
    
    //数组其他方法
}

泛型是为了解决Object接收任意类型存在类型转换的隐患.

泛型类

泛型类: 泛型类型用于类的定义中

通过泛型可以完成对一组类的操作对外开放相同的接口

普通的泛型类

public class Demo<T> {
    //name的类型为泛型,由外部指定
    private T name;

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
}

传入的实参类型需与泛型的参数类型相同

Demo<Integer> demo = new Demo<Integer>(123456);

泛型类派生子类

Demo做为父类

public class Demo<T> 

若子类也是泛型类,子类和父类的泛型类型要一致

public class DemoChild<T> extends Demo<T> 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Itu3Lvq3-1646020549921)(C:%5CUsers%5Clanlei%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5C1646017344204.png)]

若子类不是泛型类,父类要明确数据类型

public class Demo1Child extends Demo<String>

在这里插入图片描述

泛型接口

泛型接口与泛型类的定义和使用基本相同.

定义一个泛型接口

@FunctionalInterface//功能接口,只能有一个方法
public interface GenericInterface<T> {
    void show();
}

泛型类实现泛型接口,子类和接口的泛型类型要一致

public class DemoChild<T> extends Demo<T> implements GenericInterface{
    @Override
    public void show() {

    }
}

普通类实现泛型接口,接口要明确泛型的类型

public class Demo1Child extends Demo<String> implements GenericInterface<Integer>{
    @Override
    public void show() {
        
    }
}

通配符 , 上边界 ,下边界

泛型通配符

类型通配符一般使用 ? 代替具体的类型实参.

//  ?  通配符  表示实际传入的参数可以是任意的
public static void test(Demo<?> demo){
    System.out.println(demo.toString());
}
//  ?   可以传任意类型
Demo<String> demo = new Demo<>();
Demo<Integer> demo0 = new Demo<>();
test(demo);//String
test(demo0);//Integer

通配符上限

  • 类 / 接口 <? extends 实参类型>

    要求该泛型的类型,只能是实参类型或是参类型的子类类型

	//<? extends 类型>  类型通配符上限
    //该泛型的类型只能是  目标类型  及目标类型的   子类类型
    public static void test1(Demo<? extends Number> demo){
        System.out.println(demo.toString());
    }
    //上限为Number  可以传Number和子类  Integer Float...
    Demo<Number> demo1 = new Demo<>();
    test1(demo1);//上限
    Demo<Integer> demo2 = new Demo<>();
    test1(demo2);//上限

通配符下限

  • 类 / 接口 <? super 实参类型>

    要求该泛型的类型,只能说是实参类型或实参类型的父类类型

	//<? super 类型>    类型通配符下限
    该泛型的类型只能是  目标类型  及目标类型的   父类类型
    public static void test2(Demo<? super Integer> demo){
        System.out.println(demo.toString());
	//下限为Integer 可以传Integer 及 父类Number 超类Object
    Demo<Integer> demo3 = new Demo<>();
    test2(demo3);
    Demo<Number> demo4 = new Demo<>();
    test2(demo4);
    Demo<Object> demo5 = new Demo<>();
    test2(demo5);

类型擦除

泛型是Java 1.5 引入的概念,在之前没有泛型.但是泛型代码却能够和之前版本代码兼容,因为信息只存在于编译阶段,在进入JVM之前==,与泛型相关的的信息会被擦除掉==,称为类型擦除

package com.ffyc.forword.generic;

import java.lang.reflect.Field;

public class Demo<T> {
    //name的类型为泛型,由外部指定
    private T name;

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

    /**
     * 类型擦除
     * 通过  反射 查看泛型类在   运行时  的状态信息
     */
    public static void main(String[] args) throws NoSuchFieldException {
        Demo<String> demo = new Demo<>();
        demo.setName("jim");
        Field field = demo.getClass().getDeclaredField("name");
        System.out.println(field.getName()+"  type:"+field.getType());
    }
}

在这里插入图片描述
可以看到在运行时,泛型被转为了Object类型

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

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15598.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!