Java 泛型的用法

1. 泛型类

泛型类是指在类定义时使用类型参数来指定类的类型。这样可以在类的内部使用这些类型参数来定义字段、方法的返回类型和参数类型。

java 复制代码
public class Box<T> {
    private T t;

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

在这个例子中,Box 类使用了一个类型参数 T,可以在创建 Box 对象时指定具体的类型。

java 复制代码
Box<Integer> integerBox = new Box<>();
integerBox.set(10);
Integer value = integerBox.get();

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String message = stringBox.get();

2. 泛型接口

泛型接口与泛型类类似,允许在接口定义时使用类型参数。

java 复制代码
public interface Cache<K, V> {
    V get(K key);
    void put(K key, V value);
}

public class MemoryCache<K, V> implements Cache<K, V> {
    private Map<K, V> map = new HashMap<>();

    @Override
    public V get(K key) {
        return map.get(key);
    }

    @Override
    public void put(K key, V value) {
        map.put(key, value);
    }
}

在这个例子中,Cache 接口使用了两个类型参数 K 和 V,分别表示键和值的类型。MemoryCache 类实现了 Cache 接口,并使用了这些类型参数。

java 复制代码
Cache<String, Integer> cache = new MemoryCache<>();
cache.put("one", 1);
Integer number = cache.get("one");

3. 泛型方法

泛型方法是指在方法定义时使用类型参数。这样可以在方法内部使用这些类型参数来定义方法的返回类型和参数类型。

java 复制代码
public class Util {
    public static <T> T getFirst(T[] array) {
        if (array == null || array.length == 0) {
            return null;
        }
        return array[0];
    }
}

在这个例子中,getFirst 方法使用了一个类型参数 T,可以在调用方法时指定具体的类型。

java 复制代码
Integer[] intArray = {1, 2, 3};
Integer firstInt = Util.getFirst(intArray);

String[] stringArray = {"Hello", "World"};
String firstString = Util.getFirst(stringArray);

4. 类型通配符

类型通配符 ? 用于表示未知类型,可以用于方法参数和返回类型,以提高代码的灵活性。

复制代码
无界通配符:? 表示任意类型。
java 复制代码
public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.print(elem + " ");
    }
    System.out.println();
}

}

有界通配符:

复制代码
上界通配符:? extends T 表示类型参数是 T 的子类型。
java 复制代码
public static double sumOfList(List<? extends Number> list) {
    double s = 0.0;
    for (Number n : list) {
        s += n.doubleValue();
    }
    return s;
}

下界通配符:? super T 表示类型参数是 T 的父类型。

java 复制代码
public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
}

5. 泛型的类型擦除

Java 泛型在编译时会被擦除,即编译后的字节码中不包含泛型信息。这意味着在运行时,泛型类型参数会被替换为它们的上界(如果有上界)或 Object(如果没有上界)。

java 复制代码
public class Box<T> {
    private T t;

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

编译后,Box 类的字节码中 T 会被替换为 Object:

java 复制代码
public class Box {
    private Object t;

    public void set(Object t) {
        this.t = t;
    }

    public Object get() {
        return t;
    }
}

6. 泛型的限制

不能使用基本数据类型:泛型只能使用对象类型,不能使用基本数据类型。例如,不能创建 Box,但可以创建 Box。

类型参数不能是 final 类型:不能使用 final 类型作为类型参数。

静态上下文中不能使用类型参数:不能在静态方法或静态初始化块中使用类的类型参数。

类型参数不能是异常类型:不能使用异常类型作为类型参数。

相关推荐
微露清风9 分钟前
系统性学习C++-第五讲-内存管理
java·c++·学习
计算机毕业设计木哥13 分钟前
计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】
java·vue.js·spring boot·后端·课程设计
2351617 分钟前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
聪明的笨猪猪21 分钟前
Java Redis “运维”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.38 分钟前
怎么办这是Apifox里执行http://localhost:9002/goods/getByUserName?name=“张三“为什么我改了还是500?
java·网络·网络协议·http
编程饭碗39 分钟前
【Java集合】
java
岁岁岁平安40 分钟前
Java的双重检查锁机制(DCL)与懒加载的单例模式
java·单例模式·synchronized·
Jabes.yang1 小时前
Java面试场景:从Spring Boot到Kubernetes的技术问答
java· 面试· spring boot· 微服务· kubernetes· 技术栈· redis
小咕聊编程1 小时前
【含文档+PPT+源码】基于SpringBoot+Gpt个人健康管理系统
java·gpt·tomcat·毕业设计·hibernate
阿无,1 小时前
Java设计模式之工厂模式
java·开发语言·设计模式