美文网首页
一、Java高级特性(泛型)

一、Java高级特性(泛型)

作者: 大虾啊啊啊 | 来源:发表于2021-05-22 23:44 被阅读0次

一、为什么要使用泛型?

当我们在创建某个方法的时候,参数、返回值类型未知,创建某个类中的成员的时候,类型也是未知的,此时我们可以使用泛型,在我们实际调用方法的时候,或者创建具体的类对象的时候,再设置具体的类型。
或者当我们的方法在考虑到复用性的时候使用泛型。例如不同类型参数都可以接受。

二、泛型类

  • 在类中声明泛型
public class GenericClass<T> {
    private T data;

    public void setData(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}
  • 创建泛型类对象
       GenericClass<String> genericClass = new GenericClass<>();
        genericClass.setData("泛型类");
        System.out.println(genericClass.getData());

三、泛型接口

(1)创建泛型接口

public interface GenericInterface<T> {

    T getData();

    void setData(T t);
}

(2)实现泛型接口

public class GenericInterfaceImpl<T> extends implements GenericInterface<T> {
    private T t;

    @Override
    public T getData() {
        return t;
    }

    @Override
    public void setData(T t) {
        this.t = t;
    }
}

(3)创建泛型接口对象

  GenericInterface<String> genericInterface = new GenericInterfaceImpl<>();
        genericClass.setData("泛型接口");
        System.out.println(genericClass.getData());

四、泛型类的继承

(1)创建泛型父类


public abstract class GenericAbstarctClass<T> {
    abstract T getData();
    abstract void setTata(T t);

}

(2)泛型子类的继承

package com.it.test.generic;

public class GenericClassExtends<T> extends GenericAbstarctClass<T> {
    private T t;

    @Override
    T getData() {
        return t;
    }

    @Override
    void setTata(T s) {
        this.t = s;

    }
}

(3)泛型类继承对象的创建

    GenericAbstarctClass<String> genericAbstarctClass = new GenericClassExtends<>();
        genericAbstarctClass.setTata("继承使用泛型");
        System.out.printf(genericAbstarctClass.getData());

  • 注意
    我们来看以下代码,User继承了Person,但是userGener 和personGener 是两个独立的关系,不存在继承关系。而GenericClassExtends和GenericAbstarctClass才是继承关系
   GenericAbstarctClass<User> userGener = new GenericClassExtends<>();
GenericAbstarctClass<Person> personGener = new GenericClassExtends<>();

五、泛型方法

(1)创建泛型方法

   /**
     * 泛型方法
     *
     * @param t
     * @param <T>
     * @return
     */
    static <T> T function(T t) {
        return t;

    }

(2)使用泛型方法
此时function方法的参数和返回类型都是泛型,因此此时可以传递任意类型。

   System.out.println(function("泛型方法"));

六、限定类型变量

当我们希望设置泛型的类型必须要包含某个类的行为时候,可以使用限定类型变量extends。
例如我们希望泛型类中设置的泛型必须包含compareTo方法和add方法
此时我们让我们的泛型<T extends ArrayList & Comparable>。如果extends中包含了类,则类放在第一位,接口放在后面,接口可以有多个,类和接口直接都用&符号连接。
如下代码:

/**
 * 如果我们希望泛型包含指定类的方法
 * 我们需要添加限定类型变量
 * extends指定派生类,当有多个派生类的时候
 * 第一个为类,&符号后面为接口
 *
 * @param <T>
 */
public class GenericClass2<T extends ArrayList & Comparable> {

    int function(T t) {
        return t.compareTo("a");
    }

    void function2(T t) {
        System.out.println("add= "+t.add("a"));
    }

}

七、通配符类型

通配符类型使用:
? extends Person 限制了类型的上界
? super Person 限制了类型的下界
(1)personGenericType 和userGenericType 中虽然Student继承了User。但是调用function3(GenericType<Person> type)方法的时候,只能接受personGenericType 。不能接受userGenericType 。因为userGenericType 和personGenericType 不存在继承关系。
(2)所以我们需要通配符? extends Person 或者? super Person

  • ? extends Person 的意思指的是GenericType类设置的泛型只要是Person 以下的类都可以接受
  • ? super Person 的意思指的是GenericType类设置的泛型只要是Person 之上的类都可以接受
    我们可以看function4和function5方法
    如下代码:
  static void function5(GenericType<? super User> type) {
        //? super 可以获取数据
        type.setData(new User());
        type.setData(new Student());
    }

    static void function3(GenericType<Person> type) {


    }

    static void function4(GenericType<? extends Person> type) {
        //  //? super 可以设置数据
        Person person = type.getData();


    }

  GenericType<Person> personGenericType = new GenericType<>();
        GenericType<User> userGenericType = new GenericType<>();
        GenericType<Student> studentGenericType = new GenericType<>();
        //类型匹配
        function3(personGenericType);
        //类型不匹配,不能编译
        //类型必须是Person的子类
        function3(userGenericType);
        //使用? extends通配符
        //类型匹配
        function4(personGenericType);
        //类型匹配
        function4(userGenericType);

        //类型匹配
        function5(personGenericType);
        //类型不匹配类型必须是User的超类
        function5(studentGenericType);

八、泛型中的一些约束

(1)不能实例化泛型变量
(2)泛型类中的泛型,不能使用在静态方法上
(3)泛型方法可以使用在静态方法中


public class Restric<T> {
    /**
     * 不能实例化泛型变量
     *
     * @return
     */
    T getData() {
        return new T();
    }

    /**
     * 泛型类中的泛型,不能使用在静态方法上
     *
     * @param t
     * @return
     */
    static T function(T t) {
        return t;

    }

    /**
     * 泛型方法可以使用在静态方法中
     * @param e
     * @param <E>
     * @return
     */
    static <E> E funtionc2(E e) {
        return e;
    }

}

(4)泛型不能使用在基本类型中
(5)泛型不能使用instance of

      if(genericAbstarctClass instanceof GenericAbstarctClass<String> ){
      }

(6) 可以声明泛型数组,但是不能实例化

        //没问题
 GenericAbstarctClass<String>[]arrays;
        //有问题
 GenericAbstarctClass<String>[]arrays2 = new  GenericAbstarctClass<String>[10];

(7)泛型类不能派生Excetion/Throw

 class GenericInterfaceImpl<T> extends Exception  有问题

(8)不能捕获泛型类型的异常,可以抛出泛型异常

  /**
     * 不能捕获泛型类型的异常
     *
     * @param <T>
     * @return
     */
    <T extends Exception> T function() {
        try {

        } catch (T e) {

        }
    }

    /**
     * 可以抛出泛型异常
     *
     * @param e
     * @param <T>
     * @return
     * @throws T
     */
    <T extends Exception> T function2(T e) throws T {
        throw e;
    }

九、虚拟机如何实现泛型

泛型擦除。字节码中实际上是擦除了泛型,而在实际执行期间是根据泛型进行了强转、在虚拟机有有一个变量实现了弱记忆功能,记住泛型的类型。

通过匿名内部类来获取泛型类型

package com.example.myapplication;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 自定义一个泛型类
 * @param <T>
 */
public  class TypeClass<T> {

    public Type getType() {
        //获取泛型类型
        Type type = getClass().getGenericSuperclass();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        //因为泛型可能有多个,所以是一个数组
        Type[] types = parameterizedType.getActualTypeArguments();
        //测试获取第一个泛型类型
        return types[0];
    }
}

      //通过反射获取泛型类型
        //通过匿名内部类来实现,获取泛型的类型
        TypeClass<String> typeClass = new TypeClass<String>() {
        };
        Log.e("ResultActivity", "getType =  "+typeClass.getType());

相关文章

  • Java高级语言特性之泛型

    Java高级语言特性之泛型 Java泛型(generics)是JDK 5中引入的一个新特性,泛型提供了编译时类型安...

  • Kotlin泛型的高级特性(六)

    泛型的高级特性1、泛型实化2、泛型协变3、泛型逆变 泛型实化 在Java中(JDK1.5之后),泛型功能是通过泛型...

  • Java高级特性-泛型:泛型的基本用法,怎样才能少写 1 万行代

    泛型是 Java 的一个高级特性。在 Mybatis、Hibernate 这种持久化框架,泛型更是无处不在。 然而...

  • Kotlin-泛型和委托

    泛型 泛型的使用是为了程序有更好的扩展性。泛型类和泛型方法 泛型的高级特性java的泛型是通过类型擦除机制来实现的...

  • Java 高级特性——泛型

    声明这是我上课学到的, 为什么我们需要泛型? 通过两段代码我们就可以知道为何我们需要泛型 实际开发中,经常有数值类...

  • 一、Java高级特性(泛型)

    一、为什么要使用泛型? 当我们在创建某个方法的时候,参数、返回值类型未知,创建某个类中的成员的时候,类型也是未知的...

  • 通配符的上下限与泛型方法

    java零基础入门-高级特性篇(七) 泛型 下 本章阅读有难度,请谨慎阅读,如有不适,可以跳过。 本章继续讲解泛型...

  • JAVA-泛型

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

  • Java 泛型

    一、概述 1.1 什么是Java泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型...

  • Java高级特性之泛型

    前言 想写一下关于 Java 一些高级特性的文章,虽然这些特性在平常实现普通业务时不必使用,但如果想写出优雅而高扩...

网友评论

      本文标题:一、Java高级特性(泛型)

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