Java 泛型系列二:限定类型、泛型的约束与局限性

2,863 阅读2分钟

Java 泛型系列二:限定类型、泛型的约束与局限性

本文概述:

  • 本文为 Java 泛型系列第二篇文章,文章以具体业务场景,介绍了 Java 泛型当中的限定类型变量、泛型的局限性以及泛型的约束性;诸如,泛型可存在于静态中吗,泛型方法可以被static 修饰吗,泛型在异常中是如何使用的等等;

泛型:限定类型变量

  • 业务需求:限定泛型类型(拥有compareTo() 方法的类型才能被传入)

  • 代码:返回两数最小值

    //指定泛型T 上限为某一类型/接口
    package generic;
    
    public class MinValue {
    
        //定义泛型方法
        public <T extends Comparable>T minValue(T number1,T number2){
            if(number1.compareTo(number2) > 0){
                return number2;
            }else{
                return number1;
            }
        }
    
        public static void main(String[] args) {
            MinValue ma = new MinValue();
            System.out.println(ma.minValue(1,2));
        }
    }
    
  • 代码细节:

    • 编译错误出现:

      • 如果实参没有继承限定类或者实现限定接口时,将报编译错误
    • 限定类型细节:

      • 可以是类或者接口,且允许同时出现,但需遵循单继承多实现规则

      • 当类与接口混用时,需要将类写在首位

      • 受限定的泛型与其限定类型可以有多个,例如泛型T,V 均需实现接口1,2

        //不同接口以 & 进行分割
        public static<T,V extends 接口1 & 接口2>
        

泛型:泛型的约束与局限性

  • 不能是实例化泛型类型

    package generic;
    
    public class Restrict<T> {
        private T data;
        
        //正确构造方法
        public Restrict(T data){
            this.data = data;//编译错误
        }
        
        //错误构造:不能实例化类型变量
        public Restrict(){
            this.data = new T();//编译错误
        }
    }
    
  • 普通静态域(类 与 方法 )中不能引用泛型变量,但泛型方法可以被static 修饰

    package generic;
    
    public class Restrict<T> {
        private T data;
        
    	private static T instance;//编译错误
        private static <T >T getInstance;//可以的
    }
    
    • 为什么:虚拟机在创建对象时,先执行静态域代码,再指定构造代码
  • 泛型类型不能是基本类型,但可以使用其包装类型

    • double 不是对象,Double 是对象
    • Java 并不是严格面向对象(dart 就是严格面向对象的 ),其中有基本类型存在
    package generic;
    
    public class Restrict<T> {
        private T data;
    
        public static void main(String[] args) {
            Restrict<double> d;//编译错误
            Restrict<Double> D;//编译通过
        }
    }
    
  • 不能对泛型使用 instanceOf

    • 涉及到泛型擦除;

    image-20220811215706272

  • 泛型类实例,拿到的字节码是泛型类本身,也叫原生类型

    • 示例代码

      package generic;
      
      public class Restrict<T> {
          private T data;
      
          public static void main(String[] args) {
              Restrict<Double> D = new Restrict<>();
              Restrict<String> S = new Restrict<>();
      
              System.out.println(D.getClass() == S.getClass());
              System.out.println(D.getClass().getName());
              System.out.println(S.getClass().getName());
      
          }
      }
      
    • 运行截图:

      image-20220811220242265

  • 可以定义泛型数组,但是不能将其实例化

    • 实例代码:

      image-20220811220557970

  • 泛型类是不能派生自Exception、Throwable ,且异常中不能捕获泛型对象

    • 为什么限定类型可以指定为Throwable

    image-20220811221311936

  • 但是可以抛出泛型类型的异常 + 此时需要配合try - catch 语句块

    image-20220811221616670