Java 基本泛型使用方法及案例

本文详细解释了Java泛型中常见的字母类型参数(如T,K,V,E,N,S,U,V等)的含义,并通过实例展示了泛型方法、泛型类、泛型接口、通配符和有界泛型的使用。特别提到了如何在Java中使用Array.newInstance创建泛型数组以绕过类型擦除的问题。

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

在泛型中,常见的字母表示法通常用于表示类型参数,它们没有固定含义,但在惯例中被广泛使用。以下是通常用于表示泛型类型参数的一些常见字母及其惯例含义:

  • T: 表示任意类型。通常用于表示泛型方法或泛型类中的类型参数。
  • K: 表示键(Key)。通常用于表示键值对中的键的类型。
  • V: 表示值(Value)。通常用于表示键值对中的值的类型。
  • E: 表示元素(Element)。通常用于表示集合中的元素类型。
  • N: 表示数字(Number)。通常用于表示数字类型,如整数、浮点数等。
  • S,U,V 等: 用于表示第二、第三、第四个泛型类型参数。

这些字母并没有固定的含义,但是它们在代码中的使用已经成为了一种约定俗成的规范,有助于提高代码的可读性和理解性。

1. 泛型方法(Generic Methods)

public class GenericMethods {
    // 泛型方法示例
    public <T> void printArray(T[] inputArray) {
        for (T element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }
}

2. 泛型类(Generic Classes)

public class Box<T> {
    private T value;

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

    public T getValue() {
        return value;
    }
}

3. 泛型接口(Generic Interfaces)

public interface Pair<K, V> {
    K getKey();

    V getValue();
}

4. 通配符(Wildcards)

public void printList(List<?> list) {
    for (Object obj : list) {
        System.out.print(obj + " ");
    }
    System.out.println();
}

5. 有界泛型(Bounded Generics)

public double sumOfList(List<? extends Number> list) {
    double sum = 0.0;
    for (Number num : list) {
        sum += num.doubleValue();
    }
    return sum;
}

示例

import java.util.List;
import java.util.Map;

// 泛型方法示例
public class ComplexGenericExample<T, U> {

    // 泛型方法示例
    public <E, V> void printArray(E[] inputArray, V[] secondArray) {
        System.out.print("First Array: ");
        for (E element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
        
        System.out.print("Second Array: ");
        for (V element : secondArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }

    // 泛型接口示例
    public interface Pair<K, V> {
        K getKey();

        V getValue();
    }

    // 实现多个泛型接口
    public class ComplexPair<K, V, S> implements Pair<K, V>, Comparable<S> {
        private K key;
        private V value;

        public ComplexPair(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        @Override
        public int compareTo(S o) {
            // 实现 Comparable 接口的比较方法
            return 0;
        }
    }

    // 通配符示例
    public void printList(List<? extends Number> list, List<? super String> secondList) {
        System.out.print("First List: ");
        for (Number number : list) {
            System.out.print(number + " ");
        }
        System.out.println();
        
        System.out.print("Second List: ");
        for (Object obj : secondList) {
            System.out.print(obj + " ");
        }
        System.out.println();
    }

    // 有界泛型示例
    public double sumOfList(List<? extends Number> list, List<? super Integer> secondList) {
        double sum = 0.0;
        for (Number num : list) {
            sum += num.doubleValue();
        }
        secondList.add((int) sum);
        return sum;
    }

    // 主方法
    public static void main(String[] args) {
        // 泛型类实例化
        ComplexGenericExample<Double, String> complexGenericExample = new ComplexGenericExample<>();

        // 泛型方法调用
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        String[] stringArray = { "Hello", "World" };
        complexGenericExample.printArray(intArray, stringArray);

        // 实现多个泛型接口
        ComplexPair<Integer, String, Double> complexPair = complexGenericExample.new ComplexPair<>(1, "One");
        System.out.println("Key: " + complexPair.getKey() + ", Value: " + complexPair.getValue());

        // 使用通配符的方法调用
        List<Integer> intList = List.of(1, 2, 3, 4, 5);
        List<String> stringList = new ArrayList<>();
        complexGenericExample.printList(intList, stringList);

        // 使用有界泛型的方法调用
        List<Double> doubleList = List.of(1.1, 2.2, 3.3, 4.4, 5.5);
        List<Integer> integerList = new ArrayList<>();
        double sum = complexGenericExample.sumOfList(doubleList, integerList);
        System.out.println("Sum of list: " + sum);
        System.out.println("Integer List: " + integerList);
    }
}

补充: 无法直接创建泛型数组 

Box<String>[] arrayOfBoxes = new Box<String>[5]; // 这是错误的!无法创建泛型数组

为什么会出错呢?因为 Java 编译器无法确定 arrayOfBoxes 数组的确切类型。在运行时,泛型信息会被擦除,所以编译器无法保证数组的元素类型是 Box<String>。如果允许创建这样的数组,那么可能会导致类型安全问题,例如你可以向数组中添加一个不同类型的对象,从而违反了泛型的类型安全性。

可以使用如下方法

import java.lang.reflect.Array;

public class Main {
    public static void main(String[] args) {
        // 创建一个长度为 5 的 Box<String> 类型的数组
        Box<String>[] arrayOfBoxes = createArray(Box.class, 5);

        // 初始化数组的每个元素
        for (int i = 0; i < arrayOfBoxes.length; i++) {
            arrayOfBoxes[i] = new Box<String>("Item " + i);
        }

        // 打印数组的每个元素
        for (Box<String> box : arrayOfBoxes) {
            System.out.println(box.getItem());
        }
    }

    // 泛型方法,用于创建泛型数组
    @SuppressWarnings("unchecked")
    public static <T> T[] createArray(Class<T> type, int length) {
        return (T[]) Array.newInstance(type, length);
    }
}

// 泛型类 Box
class Box<T> {
    private T item;

    public Box(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}

Array.newInstance() 方法可以用于创建任意类型的数组,包括泛型数组。它接受两个参数:数组元素的类型和数组的长度。通过传入数组元素的类对象,可以在运行时创建一个与该类对象对应的数组。

在 Java 中,泛型的类型信息在编译时会被擦除,这就意味着编译器无法直接创建泛型数组,因为它无法确定泛型的确切类型。但是,通过 Array.newInstance() 方法,可以在运行时提供泛型类型的信息,从而动态地创建泛型数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值