详解 Java 泛型:核心概念与实用示例

简介: 详解 Java 泛型:核心概念与实用示例

详解 Java 泛型:核心概念与实用示例

Java 泛型(Generics)是Java SE 5引入的一项特性,旨在提高代码的可重用性和类型安全性。通过泛型,开发者可以编写一个通用的类、接口或方法,可以与多种类型一起工作,而不需要为每种类型创建不同的版本。

泛型的核心概念

泛型类(Generic Class)

泛型类是包含一个或多个类型参数的类。例如:

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

这里,T 是类型参数,可以在创建 Box 对象时指定具体的类型:

Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");

Box<Integer> integerBox = new Box<>();
integerBox.setContent(123);

泛型方法(Generic Method):

泛型方法是包含类型参数的方法。类型参数在方法的声明中被指定。例如:

public class GenericMethodExample {

    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4};
        String[] stringArray = {"A", "B", "C"};

        printArray(intArray);
        printArray(stringArray);
    }
}

泛型接口(Generic Interface):

泛型接口和泛型类类似。它们允许类型参数在接口中使用。例如:

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

public class OrderedPair<K, V> implements Pair<K, V> {
    private K key;
    private V value;

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

    public K getKey() { return key; }
    public V getValue() { return value; }
}

类型通配符(Wildcard):

泛型中的通配符用于表示未知类型。通配符有三种形式:

  • 无限制通配符(?):表示任何类型。
public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}
  • 有上限的通配符(? extends Type):表示类型是 Type 或其子类。
public void processList(List<? extends Number> list) {
    for (Number num : list) {
        System.out.println(num);
    }
}
  • 有下限的通配符(? super Type):表示类型是 Type 或其父类。
public void addNumber(List<? super Integer> list) {
    list.add(new Integer(123));
}

类型擦除(Type Erasure):

泛型在编译时会进行类型擦除,这意味着泛型类型在运行时被移除,并替换为其限定类型(如果未指定,则为 Object)。这使得泛型可以与非泛型代码互操作。

public class Box<T> {
    private T content;

    public void setContent(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

编译后:

public class Box {
    private Object content;

    public void setContent(Object content) {
        this.content = content;
    }

    public Object getContent() {
        return content;
    }
}

使用泛型的注意事项

不能创建泛型类型的实例

public class Box<T> {
    // T t = new T(); // 错误:不能直接创建泛型类型的实例
}

静态成员不能使用类型参数

public class Box<T> {
    // private static T content; // 错误:静态变量不能使用类型参数
}

泛型数组创建受限

public class Box<T> {
    // T[] array = new T[10]; // 错误:不能直接创建泛型数组
}

示例:使用泛型的栈

public class GenericStack<T> {
    private List<T> stack = new ArrayList<>();

    public void push(T element) {
        stack.add(element);
    }

    public T pop() {
        if (!stack.isEmpty()) {
            return stack.remove(stack.size() - 1);
        }
        return null;
    }

    public boolean isEmpty() {
        return stack.isEmpty();
    }

    public static void main(String[] args) {
        GenericStack<String> stringStack = new GenericStack<>();
        stringStack.push("Hello");
        stringStack.push("World");
        System.out.println(stringStack.pop()); // 输出:World

        GenericStack<Integer> intStack = new GenericStack<>();
        intStack.push(1);
        intStack.push(2);
        System.out.println(intStack.pop()); // 输出:2
    }
}

结论

Java 泛型提供了一种类型安全的方式来实现通用编程。它们不仅提高了代码的可读性和可维护性,还避免了类型转换的错误。在编写通用类、接口和方法时,泛型是一个强大的工具。

目录
相关文章
|
4天前
|
安全 Java 编译器
Android面试题之Java 泛型和Kotlin泛型
**Java泛型是JDK5引入的特性,用于编译时类型检查和安全。泛型擦除会在运行时移除类型参数,用Object或边界类型替换。这导致几个限制:不能直接创建泛型实例,不能使用instanceof,泛型数组与协变冲突,以及在静态上下文中的限制。通配符如<?>用于增强灵活性,<? extends T>只读,<? super T>只写。面试题涉及泛型原理和擦除机制。
14 3
Android面试题之Java 泛型和Kotlin泛型
|
1天前
|
Java 编译器 容器
Java 泛型
Java 泛型
19 10
|
1天前
|
安全 Java 编译器
在Java中,什么是类型擦除机制,如何有效运用泛型的类型擦除机制?
Java的类型擦除机制在编译时移除了泛型的类型参数信息,生成的字节码不包含泛型,以确保向后兼容。这导致运行时无法直接获取泛型类型,但编译器仍做类型检查。为了有效利用类型擦除,应避免运行时类型检查,使用通配符和界限增加代码灵活性,通过超类型令牌获取泛型信息,以及利用泛型方法来保证安全性。理解这些策略能帮助开发者编写更安全的泛型代码。
26 8
|
2天前
|
Java
死锁是线程间争夺资源造成的无限等待现象,Java示例展示了两个线程各自持有资源并等待对方释放,导致死锁。`
【6月更文挑战第20天】死锁是线程间争夺资源造成的无限等待现象,Java示例展示了两个线程各自持有资源并等待对方释放,导致死锁。`volatile`保证变量的可见性和部分原子性,确保多线程环境中值的即时更新。与`synchronized`相比,`volatile`作用于单个变量,不保证原子操作,同步范围有限,但开销较小。`synchronized`提供更全面的内存语义,保证原子性和可见性,适用于复杂并发控制。
12 3
|
2天前
|
存储 算法 Java
Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。
【6月更文挑战第21天】Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。简单哈希表实现未涵盖冲突解决和删除操作。
10 1
|
3天前
|
安全 Java 开发者
Java泛型详解
Java泛型详解
13 2
|
4天前
|
Java 开发者
Java面向对象编程(OOP)的四个主要概念
【6月更文挑战第19天】Java OOP的基石是封装、抽象、继承和多态。封装是通过类隐藏数据细节;抽象简化复杂性,用接口和抽象类实现;继承让子类从父类继承属性和行为,促进代码重用;多态一个接口可有多种形态,分编译时和运行时。这些概念支持灵活且可扩展的软件设计。
8 1
|
5天前
|
Java 编译器
在 Java 中,重写(Override)和重载(Overload)是两种不同的概念,用于实现多态性。它们有着不同的作用和使用场景。
在 Java 中,重写(Override)和重载(Overload)是两种不同的概念,用于实现多态性。它们有着不同的作用和使用场景。
|
8天前
|
JSON IDE Java
Java反射详解:核心概念、使用方法与实际应用
Java反射详解:核心概念、使用方法与实际应用
17 2
|
8天前
|
安全 Java
深入理解 Java 泛型工厂方法:类型安全与灵活性的结合
深入理解 Java 泛型工厂方法:类型安全与灵活性的结合
9 1