hooyantsing's Blog

JavaSE强化教程泛型,由点到面的讲解了整个泛型体系

字数统计: 1.3k阅读时长: 5 min
2022/06/01

视频源:JavaSE强化教程泛型,由点到面的讲解了整个泛型体系

泛型类、接口

泛型类

  • 泛型类的定义语法

    1
    2
    3
    class 类名称<泛型标识,泛型标识,...> {
    private 泛型标识 变量名;
    }
  • 常用的泛型标识:T、E、K、V

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Generic<T> {
private T key;

public Generic(T key) {
this.key = key;
}

public T getKey() {
return key;
}

public void setKey(T key) {
this.key = key;
}
}
  • 使用语法

    1
    类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
  • Java 1.7 以后,后面的<>中的具体数据类型可以省略不写

    1
    类名<具体的数据类型> 对象名 = new 类名<>();

泛型类注意事项

  • 泛型类,如果没有指定具体的数据类型,操作类型是 Object;
  • 泛型的类型参数只能是类类型,不能是基本数据类型;
  • 泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ProductGetter<T> {
Random random = new Random();
// 奖品
private T product;
// 奖品池
ArrayList<T> list = new ArrayList<>();

// 添加奖品
public void addProduct(T t) {
list.add(t);
}

// 抽奖
public T getProduct() {
product = list.get(random.nextInt(list.size()));
return product;
}
}

从泛型类派生子类

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

    1
    2
    3
    class ChildGeneric<T> extends Generic<T>
    // 也可以增加泛型类型
    class ChildGeneric<T,E,K> extends Generic<T>
  • 子类不是泛型类,父类要明确泛型的数据类型

    1
    class ChildGeneric extends Generic<String>

泛型接口

  • 泛型接口的定义语法

    1
    2
    3
    interface 接口名称<泛型标识,泛型标识,...> {
    泛型标识 方法名();
    }

泛型接口的使用

  • 实现类不是泛型类,接口要明确数据类型;
  • 实现类也是泛型类,实现类和接口的泛型类型要一致。
1
2
3
public interface Generator<T> {
T getKey();
}
1
2
public class Pair<T> implements Generator<T>
public class Pair<T,E,K> implements Generator<T>
1
public class Apple implements Generator<String>

泛型方法

  • 泛型类,是在实例化类的时候指明泛型的具体类型;
  • 泛型方法,是在调用方法的时候指明泛型的具体类型。
1
2
3
修饰符 <T,E,...> 返回值类型 方法名(形参列表) {
方法体...
}
  • public 与返回值中间 <T> 非常重要,可以理解为声明此方法为泛型方法;
  • 只有声明了 <T> 的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法;
  • <T> 表明该方法将使用泛型类型 T,此时才可以在方法中使用泛型类型 T;
  • 与泛型类的定义一样,此处 T 可以随便写为任意表示,常见的如 T、E、K、V 等形式的参数常用于表示泛型。
1
2
3
public <E> E getProduct(ArrayList<E> list) {
return list.get(random.nextInt(list.size()));
}

泛型方法可以被 static 修饰。

1
public static <T,E,K> void printType(T t,E e,K k)

泛型方法与可变参数

1
2
3
4
5
public <E> void print(E... e) {
for(E e1 : e) {
System.out.println(e);
}
}

泛型方法总结

  • 泛型方法能使方法独立于类而产生变化;
  • 如果 static 方法要使用泛型能力,就必须使其成为泛型方法。

类型通配符

什么是类型通配符

  • 类型通配符一般是使用 ? 代替具体的类型实参;
  • 所以,类型通配符是类型实参,而不是类型形参。

类型通配符的上限

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

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

eg 01

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
Box<Number> box1 = new Box<>;
showBox(box1);
Box<Integer> box2 = new Box<>;
showBox(box2);
}

// 向上父类只能到Number (Integer是Number子类)
public static void showBox(Box<? extends Number> box) {
Numaber first = box.getFirst();
}

eg 02

继承关系:Animal -> Cat -> MiniCat

1
public class Animal{}
1
public class Cat extends Animal{}
1
public class MiniCat extends Cat{}
1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<>();
ArrayList<Cat> cats = new ArrayList<>();
ArrayList<MiniCat> miniCat = new ArrayList<>();

showAnimal(animals); // 编译错误
showAnimal(cats);
showAnimal(miniCat);
}

public static void showAnimal(ArrayList<? extends Cat> list) {}

注意:“类型通配符的上限” 方法不允许添加元素

1
2
3
4
5
public static void showAnimal(ArrayList<? extends Cat> list) {
list.add(new Animal()); // 编译错误
list.add(new Cat()); // 编译错误
list.add(new MiniCat()); // 编译错误
}

类型通配符的下限

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

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

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<>();
ArrayList<Cat> cats = new ArrayList<>();
ArrayList<MiniCat> miniCat = new ArrayList<>();

showAnimal(animals);
showAnimal(cats);
showAnimal(miniCat); // 编译错误
}

public static void showAnimal(ArrayList<? super Cat> list) {}

注意:“类型通配符的下限” 方法允许添加元素,不保证元素类型约束要求。

以下章节未学习

类型擦除

泛型与数组

泛型和反射

CATALOG
  1. 1. 泛型类、接口
    1. 1.1. 泛型类
    2. 1.2. 泛型类注意事项
    3. 1.3. 从泛型类派生子类
    4. 1.4. 泛型接口
    5. 1.5. 泛型接口的使用
  2. 2. 泛型方法
    1. 2.1. 泛型方法与可变参数
    2. 2.2. 泛型方法总结
  3. 3. 类型通配符
    1. 3.1. 什么是类型通配符
    2. 3.2. 类型通配符的上限
    3. 3.3. 类型通配符的下限
  4. 4. 类型擦除
  5. 5. 泛型与数组
  6. 6. 泛型和反射