Java开发之泛型

发布于:2024-07-22 ⋅ 阅读:(56) ⋅ 点赞:(0)

#来自ゾフィー(佐菲)

1 泛型的作用

  • 适用于多种数据类型执行相同的代码。
  • 泛型中的类型在使用时指定,不需要强制类型转换(出现异常 java.lang.ClassCastException)。

2 泛型类和泛型接口

泛型:参数化类型,将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

//泛型类
public class NormalGeneric<T> {
    private T data;

    public NormalGeneric(T data) {
        this.data = data;
    }
}

//泛型接口
public interface IGenerator<T> {
    T getData();
}
//1.实现泛型接口方式
public class ImplGenerator1<T> implements IGenerator<T> 

//2.实现泛型接口方式
public class ImplGenerator2 implements IGenerator<String> 

3 泛型方法

可以在任何地方定义,普通类、泛型类等。

public class GeneratorMethod {
    public <T> T getMethod(T... a) { //使用 <T>
        return a[a.length / 2];
    }

    public static void main(String[] args) {
        GeneratorMethod generatorMethod = new GeneratorMethod();
        String s = generatorMethod.getMethod("Java", "C++");
        System.out.println(s);
    }
}

public class NoGeneratorMethod<T> {
    private T key;
    public NoGeneratorMethod(T key){
        this.key = key;
    }
    
    public T getKey() { //注意:不是泛型方法
        return key;
    }
}   

4 限定类型变量

对类型变量进行约束,,可以在泛型类、泛型接口、泛型方法上世使用。

public <T extends Comparable> T max(T a, T b) {
      return a.compareTo(b) > 0 ? a : b;
}

//extends左右都允许有多个,如 T,V extends Comparable & Serializable
//但是只允许有一个类,且必须在列表第一个位置
public <T extends Comparable & Serializable> T min(T a, T b) {
      return a.compareTo(b) > 0 ? b : a;
}

5 注意

//不能使用类型变量
public static  T instance;

//基本数据类型不支持
NormalGeneric<int> a = new NormalGeneric<>();//出错

//创建数组不支持
NormalGeneric<Integer>[] a = new NormalGeneric<>[9];//出错

//不能实例化类型变量
this.data = new T();

//不能 extends Exception、Throwable,不能捕获泛型类实例 
public static class MyException<T> extends Exception {
     public <T extends Throwable> void doWork(T t) {
           try {

           } catch (T e) {
                
           }
     }
    
    public <T extends Throwable> void doWork1(T t) throws T{
           try {

           } catch (Throwable e) {
                throw e;//可以抛出泛型异常
           }
     }
}

6 通配符类型

public class Fruit {}

public class Apple extends Fruit {}

public class Banana extends Fruit {}

public class GreenBanana extends Banana {}

public class GenericType<T> {
    private T data;

    public T getData() {
        return data;
    }

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

6.1 ? extends X

表示类型的上界,类型参数是 X 的子类。

public static void main(String[] args) {
        GenericType<Fruit> a = new GenericType<>();
        GenericType<? extends Fruit> b = new GenericType<>();
        GenericType<Apple> c = new GenericType<>();

        a = c; //出错 
        b = c; //可以 <? extends Fruit> 表示上界是 Fruit ,子类当然可以。
        Apple apple = new Apple();
        Banana banana = new Banana();
        b.setData(apple);//出错 上限:set 不可
        b.setData(banana);//出错 
        Fruit fruit = b.getData();//可以,上限:get 可行
}

6.2 ? super X

表示类型的下界,类型参数是 X 的超类

 public static void main(String[] args) {   
       GenericType<? super Banana> a = new GenericType<>();
       GenericType<GreenBanana> b = new GenericType<>();
       GenericType<Fruit> c = new GenericType<>();
       a = b;//出错
       a = c;//可以 <? super Banana> 表示下界是 Banana ,他的超类当然可以
     
       Banana banana = new Banana();
       GreenBanana greenBanana = new GreenBanana();
       Fruit fruit = new Fruit();
       a.setData(banana);//可以
       a.setData(greenBanana);//可以
       a.setData(fruit);//出错 <? super Banana> 表示下界是 Banana,Fruit 超了,强记
       Object data = a.getData();//唯一取值是 Object
}

6.3 无限定的通配符 ?

表示对类型没有什么限制,可以把 ?看成所有类型的父类,如Pair< ?>;

比如:

ArrayList al=new ArrayList(); 指定集合元素只能是T类型

ArrayList al=new ArrayList();集合元素可以是任意类型,这种没有意义,一般是方法中,只是为了说明用法。

在使用上:

? getFirst() : 返回值只能赋给 Object,;

void setFirst(?) : setFirst 方法不能被调用, 甚至不能用 Object 调用;

7 虚拟机实现泛型

类型擦除,Java 泛型是伪泛型,仅仅是对方法的 Code 属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息,能通过反射手段取得参数化类型,使用 Signature 存储一个方法在字节码层面的特征签名(泛型类型)。


网站公告

今日签到

点亮在社区的每一天
去签到