MST

星途 面试题库

面试题:Java泛型在集合框架自定义实现中的应用

假设你要自定义一个类似于Java集合框架中List的结构,并且要充分运用Java泛型。请描述实现过程中如何处理泛型类型参数的边界、如何保证类型安全,以及如何处理不同类型数据的存储和读取。同时,请给出关键代码示例。
48.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

处理泛型类型参数的边界

  1. 上界:使用 extends 关键字来限制类型参数必须是某个类或接口的子类或实现类。例如,若希望自定义的 List 只能存储 Number 及其子类的对象,可以这样定义泛型参数:class MyList<T extends Number>。这确保了在这个 MyList 中只能添加 Number 及其子类(如 IntegerDouble 等)的实例。
  2. 下界:使用 super 关键字来限制类型参数必须是某个类或接口的超类。例如,class MyList<T super Integer> 表示 T 必须是 IntegerInteger 的超类,这样在添加元素时,只要是 Integer 类型或其子类类型的元素都可以添加进来。

保证类型安全

  1. 使用泛型检查:Java 的泛型在编译时进行类型检查,确保类型的正确性。例如,定义 MyList<Integer> 后,尝试添加非 Integer 类型的元素会在编译时报错。
  2. 避免类型转换错误:通过泛型,在获取元素时无需进行强制类型转换,减少了 ClassCastException 的风险。例如,从 MyList<Integer> 中获取元素时,编译器已经知道元素类型是 Integer,无需手动转换。

处理不同类型数据的存储和读取

  1. 存储:在定义泛型类型参数后,存储元素时确保添加的元素类型与泛型类型参数一致。例如,MyList<String> 只能添加 String 类型的元素。
  2. 读取:读取元素时,由于泛型已经指定了类型,无需进行类型转换。例如,从 MyList<Integer> 中读取元素时,直接得到 Integer 类型的对象。

关键代码示例

import java.util.Arrays;

public class MyList<T> {
    private Object[] elements;
    private int size;
    private static final int DEFAULT_CAPACITY = 10;

    public MyList() {
        elements = new Object[DEFAULT_CAPACITY];
        size = 0;
    }

    public void add(T element) {
        ensureCapacity();
        elements[size++] = element;
    }

    @SuppressWarnings("unchecked")
    public T get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException();
        }
        return (T) elements[index];
    }

    private void ensureCapacity() {
        if (size == elements.length) {
            elements = Arrays.copyOf(elements, elements.length * 2);
        }
    }

    public int size() {
        return size;
    }
}

以下是测试代码:

public class Main {
    public static void main(String[] args) {
        MyList<Integer> myList = new MyList<>();
        myList.add(1);
        myList.add(2);
        Integer num = myList.get(0);
        System.out.println(num);
    }
}