Java基础——泛型 基础介绍

在Java中,泛型是十分强大的功能,它允许我们在类、方法和接口中使用类型参数,提供安全且灵活的代码。反省通过让你指定通用类型参数来实现“类型独立性”,避免显式的类型转换(数据类型的强转肯定都用过),同时提高了代码的可读性和可维护性。

1.在类上的应用

泛型类指的是在类定义时使用类型参数(比如<T>, <E>, <K,V>等)。这种类能够处理多种类型,而不必为每种类型编写多个相似的类。

  • <T>:泛型类型参数,表示任意类型。通常用于类、方法的单一类型参数。
  • <E>:泛型元素类型参数,通常用于表示集合类中元素的类型,如 List<E>Set<E> 等。
  • <K, V>:泛型键值对类型参数,常用于表示映射类(如 Map<K, V>)的键值对类型。

注:这些字母只是符号,代表不同的泛型类型参数,命名可以根据需求进行调整,其他字母也可以使用,其本质上就是一个占位符而已,没有特定的功能,但 Java 的社区约定了这些字母的使用方式,帮助代码更具可读性和一致性,最好还是遵守这些默认的编程规范。

public class Box<T> {
    private T value;

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

    public T get() {
        return value;
    }
}

===========================使用示例======================
Box<Integer> intBox = new Box<>();
intBox.set(10);  // T 被替换为 Integer 类型
Integer value = intBox.get();  // 返回类型为 Integer
  • 在实例化时,T 被替换为具体的类型(如 IntegerString)。
  • 泛型类提供了类型安全性,在编译时就可以检查类型是否匹配。

2.在方法上的应用

泛型方法是指方法本身使用泛型,允许方法在调用时指定类型。它与泛型类不同,泛型参数只作用于该方法。

public class Util {
    public static <T> void printArray(T[] array) {  // <T> 表示这是一个泛型方法
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}
  • public static <T> 表示定义一个泛型方法,并且 T 只在该方法的作用域内有效。
  • 方法的参数 T[] array 表明它可以接受任何类型的数组作为参数。

使用

Integer[] intArray = {1, 2, 3};
String[] strArray = {"apple", "banana", "cherry"};

Util.printArray(intArray);  // 输出 1 2 3
Util.printArray(strArray);  // 输出 apple banana cherry
  • 通过 <T> 声明泛型参数后,调用该方法时可以传入不同类型的参数。
  • 编译器会自动根据方法传入的参数类型推断泛型类型。

3. 通配符的使用

通配符是 Java 泛型中用于表示未知类型的符号。常见的通配符有三种类型:

  1. ?:表示未知类型。
  2. ? extends T:表示一个类型为 T 或其子类型的类型。
  3. ? super T:表示一个类型为 T 或其父类型的类型。

3.1 ?:表示任何类型

?是最基本的通配符,表示任何类型。通常用于不关系具体类型的情况下。

List<?> list = new ArrayList<String>();  // 可以是任何类型的 List

3.2 ? extends T :表示某一个类型的子类型

? extends T 表示类型为 TT 的子类。这个通配符通常用于读取数据,因为它允许你读取 TT 的子类的元素。

public static void printList(List<? extends Number> list) {
    for (Number num : list) {
        System.out.println(num);
    }
}

List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
printList(intList);  // 适用于 List<Integer>
  • ? extends T 允许传入 TT 的任何子类(包括 IntegerDouble 等)。
  • 通常用于读取数据,因为你可以读取 TT 的任何子类,但不能向集合中添加元素(除了 null)。

3.3 ? super T:表示某一个类型的父类型

? super T 表示类型为 TT 的父类。这个通配符通常用于向集合中添加数据,因为它允许你添加 TT 的子类的元素。

public static void addNumbers(List<? super Integer> list) {
    list.add(10);  // 可以安全地添加 Integer 或其子类
}

List<Number> numberList = new ArrayList<>();
addNumbers(numberList);  // 可以传入 List<Number> 或 List<Object>
  • ? super T 允许传入 TT 的任何父类(包括 Object)。
  • 通常用于向集合中添加数据,因为它保证你可以添加 T 类型或其子类的对象。
通配符的总结
通配符含义用法
?表示任何类型用于不关心类型时(例如:List<?>
? extends T表示 TT 的子类用于读取数据(例如:List<? extends Number>
? super T表示 TT 的父类用于向集合中添加数据(例如:List<? super Integer>
  • ? 用于无法确定具体类型时,例如在某些方法中只需要通用类型参数时。
  • ? extends T 用于方法参数中,当你只需要读取集合中的元素,且知道它们是 TT 的子类时。
  • ? super T 用于方法参数中,当你需要向集合中添加元素,且知道它们是 TT 的父类时。

 4. 泛型的限制

尽管泛型在 Java 中非常强大,但它也有一些限制:

  • 不能使用基本数据类型:Java 的泛型只能使用对象类型,不能直接使用基本数据类型,如 intchar 等。你可以使用包装类,如 IntegerCharacter 等。

  • 不能创建泛型数组:由于泛型类型在运行时会被擦除,所以你不能创建泛型数组。

// 错误,不能创建泛型数组
// T[] array = new T[10];

// 正确,使用 Object 数组
Object[] array = new Object[10];
  • 类型擦除:Java 泛型使用类型擦除(Type Erasure)机制,在运行时泛型类型信息被擦除,只保留原始类型。因此,你不能通过反射获取泛型的实际类型。

public class Box<T> {
    // 在运行时 T 会被擦除成 Object
}

注:Java 泛型中,?(通配符)和字母(如 TEKV 等)的泛型类型参数的确都能够表示某种类型,但它们的使用场景和目的有很大的区别。简而言之,字母泛型通常是在定义类、方法或者接口时用于表示某个类型,而通配符 ?则是在使用这些类、方法时表示任意类型,并且具有更强的灵活性。

5. 总结

  • 字母泛型:用于定义类或方法时,表示一个占位符类型。类型在使用时确定,编译器会进行类型检查。
  • 通配符 ?:用于方法参数中,表示一个未知类型。在方法内部,? 提供了更灵活的类型接受能力,同时通过 ? extends T? super T 可以限定操作范围(如只允许读取、只允许写入)。
  • 通配符增加了代码的灵活性,尤其在处理泛型集合时,避免了类型的严格限制,使得方法能够接受多种类型的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新停浊酒杯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值