廖雪峰java教程学习笔记——泛型

本文深入介绍了Java中的泛型概念,包括泛型的定义、使用方式、多类型泛型、泛型的限制以及擦拭法(Type Erasure)。通过示例展示了泛型在类、接口、集合操作中的应用,并探讨了泛型与反射的关系。此外,还提到了泛型的继承和通配符的使用,如extends和super通配符,以及它们在读写操作中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义泛型

泛型用一套代码套用各种类型。与C++ template模板一样。
在这里插入图片描述
<T>表示泛型T。T换成任意字符串都行,比如<X>

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() {
        return first;
    }
    public T getLast() {
        return last;
    }
}

Pair<String> p = new Pair<String>("a", "b");

多类型泛型:

public class Pair<T, K> {
    private T first;
    private K last;
    public Pair(T first, K last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public K getLast() { ... }
}

Pair<String, Integer> p = new Pair<>("test", 123);

使用泛型

类使用泛型

List<String> list = new ArrayList<String>();

接口使用泛型

Arrays.sort(Object[])可以对任意数组进行排序,但待排序的元素必须实现Comparable<T>这个泛型接口:

public interface Comparable<T> {
    /**
     * 返回负数: 当前实例比参数o小
     * 返回0: 当前实例与参数o相等
     * 返回正数: 当前实例比参数o大
     */
    int compareTo(T o);
}

例子

package oop_package.src.com.itranswarp.sample;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Person[] ps = new Person[] {
                new Person("Bob", 61),
                new Person("Alice", 88),
                new Person("Lily", 75),
        };
        Arrays.sort(ps);
        System.out.println(Arrays.toString(ps));
    }
}

class Person implements Comparable<Person> {
    String name;
    int score;
    Person(String name, int score) {
        this.name = name;
        this.score = score;
    }
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }
    public String toString() {
        return this.name + "," + this.score;
    }
}

实现原理:擦拭法 Type Erasure

JVM将<T>替换为Object处理,需要转型的时候,根据<T>实现安全的强制转型:

public class Pair {
    private Object first;
    private Object last;
    public Pair(Object first, Object last) {
        this.first = first;
        this.last = last;
    }
    public Object getFirst() {
        return first;
    }
    public Object getLast() {
        return last;
    }
}

所以有了以下局限:

  1. <T>是Object,所以不能是基本类型:Pair<int> p = new Pair<>(1, 2); // compile error!
  2. 无法取得泛型的具体Class,无论T的类型是什么,getClass()返回同一个Class实例,因为编译后它们全部都是Pair
  3. 无法判断带泛型的类型,if (p instanceof Pair<String>) {} // Compile error:
  4. 不能实例化T类型,因为new T()都变成了new Object()

覆写泛型类的方法时,要避开继承自Object的:

// Compile error
public class Pair<T> {
    public boolean equals(T t) {  //因为会被擦拭成 equals(Object t)
        return this == t;
    }
}

// right
public class Pair<T> {
    public boolean same(T t) {
        return this == t;
    }
}

泛型继承

//父类指定过了具体类型,编译器就知道了,不用再视为Object了
public class IntPair extends Pair<Integer> {
}

IntPair ip = new IntPair(1, 2);

引入泛型后的Java类型系统结构

引入泛型后,Class不够用了,实际的类型系统结构如下:

                      ┌────┐
                      │Type│
                      └────┘
                         ▲
                         │
   ┌────────────┬────────┴─────────┬───────────────┐
   │            │                  │               │
┌─────┐┌─────────────────┐┌────────────────┐┌────────────┐
│Class││ParameterizedType││GenericArrayType││WildcardType│
└─────┘└─────────────────┘└────────────────┘└────────────┘

extends通配符

使用extends通配符表示可以读,不能写:

int sumOfList(List<? extends Integer> list) {
    int sum = 0;
    for (int i=0; i<list.size(); i++) {
        Integer n = list.get(i);
        sum = sum + n;
    }
    return sum;
}

使用类似<T extends Number>定义泛型类时表示:泛型类型限定为Number以及Number的子类:

public class Pair<T extends Number> { ... }

super通配符

//TODO

泛型和反射

//TODO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值