自定义泛型

SOBER大约 3 分钟

自定义泛型

自定义泛型类

基本语法

class 类名 <T, R...> { // ... 表示可以有多个泛型
    成员
}

注意细节

  1. 普通成员可以使用泛型(属性、方法)
  2. 使用泛型的数组,不能初始化
  3. 静态方法中不能使用类的泛型
  4. 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
  5. 如果在创建对象时,没有指定类型,默认为 Object

示例

/**
 * 1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
 * 2. T,R,M 泛型的标识符,一般是单个大写字母
 * 3. 泛型标识符可以有多个
 * 4. 普通成员可以使用泛型(属性、方法)
 * 5. 使用泛型的数组,不能初始化
 * 6. 静态方法和静态属性(static)中不能使用类的泛型,所以会报错
 */
class Tiger<T, R, M>{
    String name;
    R r;
    M m;
    T t;
    T[] ts;
    
    /**
     * 因为静态是和类相关的,在类加载时,对象还没有创建所以,
     * 所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
     */
    static R r2; // 报错
    public static void m1(M m) {} // 报错
}

泛型接口

基本语法

interface 接囗名<T, R...>{
}

注意细节

  1. 接口中,静态成员也不能使用泛型(这个和泛型类规定一样)
  2. 泛型接口的类型,在 继承接口 或者 实现接口 时确定
  3. 没有指定类型,默认为 Object

示例

interface IUsb<U, R> {
    int n = 10;
    U name; // 不能这样使用,因为在接口中都是静态属性
    R get(U u); // 普通方法中,可以使用接口泛型
    void hi(R r); // 普通方法中,可以使用接口泛型
}

/**
 * 泛型接口的类型,在 继承接口 或者 实现接口 时确定
 * IA 继承了 IUsb 并且规定 U 的类型为 String R 的类型为 Double
 */
interface IA extends IUsb<String, Double> {}

/**
 * 当我们去实现 IA 接口时,因为 IA 在继承 IUsU 接口时,指定了 U 为 String R 为 Double
 * 因此,在实现 IUsu 接口的方法时,使用 String 替换 U,Double 替换 R
 */
class AA implements IA{
    @Override
    public Double get(String s) {
        return null;
    }

    @Override
    public void hi(Double aDouble) {

    }
}

/**
 * 实现接口时,直接指定泛型接口的类型
 * 给 U 指定 Integer 给 R 指定了 Float
 * 所以,当我们实现 IUsb 方法时,会使用 Integer 替换 U,使用 Float 替换 R
 */
class BB implements IUsb<Integer, Float> {
    @Override
    public Float get(Integer integer) {
        return null;
    }

    @Override
    public void hi(Float aFloat) {

    }
}

泛型方法

基本语法

修饰符 <T, R..>返回类型 方法名(参数列表){
}

注意细节

  1. 泛型方法,可以定义在普通类中,也可以定义在泛型类中
  2. 当泛型方法被调用时,类型会确定
  3. public void eat(E e){},修饰符后没有 <T,R..> eat 方法不是泛型方法,而是使用了泛型

示例

package commonGenericity;

import java.util.ArrayList;
import java.util.function.IntToDoubleFunction;

public class customGenerics {
    public static void main(String[] args) {
        Car car = new Car();
        car.fly("宝马", 1000);
        System.out.println("==============================");
        car.fly(2000, 300);

        /**
         * 测试
         * T ---> String, R ---> ArrayList
         */
        Fish<String, ArrayList> stringIntegerFish = new Fish<>();
        stringIntegerFish.hello(new ArrayList(), 11.3f);
    }
}

class Car { // 普通类

    public void run() {}; // 普通方法

    /**
     * 说明
     * 1. <T, R> 就是泛型
     * 2. 是提供给 fly 使用的
     */
    public <T, R> void fly(T t, R r) { // 泛型方法
        System.out.println(t.getClass()); // String
        System.out.println(r.getClass()); // Integer
    }
}

class Fish<T, R> { // 泛型类
    public void run() {} // 普通方法
    public<U, M> void eat(U u, M m) {} // 泛型方法

    /**
     * 说明
     * 1. 下面 hi 方法不是泛型方法
     * 2. 是 hi 方法使用了类声明的 泛型
     */
    public void hi(T t) {}

    /**
     * 泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
     */
    public<K> void hello(R r, K k){
        System.out.println(r.getClass());
        System.out.println(k.getClass());
    }
}