java 之 泛型的详细介绍

在这里插入图片描述


当我们谈到“泛型”时,我们实际上是在谈论一种在编程中用来处理不同类型数据的方法。想象一下,你写了一个很好用的方法或者类,但是它只能处理一种特定类型的数据,如果你想处理其他类型,你就得重写或者重新实现。这时,泛型就派上用场了。

1. 为什么需要泛型?

考虑一个简单的例子,比如一个存储数据的盒子(Box)。你可能想要一个可以存储整数的盒子,也可能需要一个可以存储字符串的盒子。如果没有泛型,你可能需要为每一种数据类型写一个不同的盒子类。

泛型就是为了解决这样的问题。它允许你写一个通用的类或者方法,可以适用于多种数据类型,而不用为每一种类型写不同的代码。

2. 泛型的基本概念

在使用泛型时,我们通常会看到一些带尖括号的符号 <T>,其中 T 是类型的占位符。这个 T 可以是任何你希望使用的数据类型。当你实际使用泛型时,你会将这个占位符替换成你实际想要的类型。

3. 泛型类的例子

比如,有一个 Box 类,你可以用它来存储各种类型的数据:

public class Box<T> {
    
    
    private T value;

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

    public T getValue() {
    
    
        return value;
    }
}

这里的 <T> 表示这是一个泛型类,T 是一个占位符,代表实际的类型。你可以创建一个存储整数的盒子:

Box<Integer> intBox = new Box<>(42);

或者创建一个存储字符串的盒子:

Box<String> stringBox = new Box<>("Hello, Generics!");

4. 泛型方法的例子

同样,你也可以在方法中使用泛型。比如,有一个泛型方法,可以打印任意类型的数据:

public class Utils {
    
    
    public static <T> void printValue(T value) {
    
    
        System.out.println("Value: " + value);
    }
}

你可以用这个方法来打印整数:

Utils.printValue(42);

或者打印字符串:

Utils.printValue("Hello, Generics!");

5. 泛型的好处

  • 代码重用: 你可以编写更通用、可重用的代码,而不用为每一种数据类型写不同的实现。
  • 类型安全: 编译器会在编译时检查类型,防止一些在运行时可能出现的类型错误。
  • 简化代码: 不再需要进行强制类型转换,代码更加清晰简洁。

泛型可能在一开始看起来有点抽象,但一旦你理解了它的基本概念,你会发现它是一种非常有用的工具,能够让你的代码更加灵活、通用和安全。

泛型使用的位置

泛型可以在很多不同的位置使用,包括类、接口、方法等。下面是一些常见的使用位置:

1. 泛型类(Generic Class):

public class Box<T> {
    
    
    private T value;

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

    public T getValue() {
    
    
        return value;
    }

    public static void main(String[] args) {
    
    
        // 使用泛型类存储整数
        Box<Integer> intBox = new Box<>(42);
        int intValue = intBox.getValue();

        // 使用泛型类存储字符串
        Box<String> stringBox = new Box<>("Hello, Generics!");
        String stringValue = stringBox.getValue();
    }
}

在类的声明中,使用 <T> 表示这是一个泛型类,T 是一个类型参数。

2. 泛型接口(Generic Interface):

public interface Pair<T> {
    
    
    T getFirst();
    T getSecond();
}

// 实现泛型接口
class OrderedPair<T> implements Pair<T> {
    
    
    private T first;
    private T second;

    public OrderedPair(T first, T second) {
    
    
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
    
    
        return first;
    }

    public T getSecond() {
    
    
        return second;
    }

    public static void main(String[] args) {
    
    
        // 创建存储整数的OrderedPair对象
        OrderedPair<Integer> pair = new OrderedPair<>(10, 20);
        int firstValue = pair.getFirst();
        int secondValue = pair.getSecond();
    }
}

同样,在接口的声明中,使用 <T> 表示这是一个泛型接口。

3. 泛型方法(Generic Method):

public class Utils {
    
    
    public static <T> void printValue(T value) {
    
    
        System.out.println("Value: " + value);
    }

    public static void main(String[] args) {
    
    
        // 调用泛型方法,编译器会根据传入参数的类型进行类型推断
        printValue("Hello, Generics!");
        printValue(42);
    }
}

在方法的返回类型之前,使用 <T> 表示这是一个泛型方法。泛型方法允许你在调用时指定类型参数,而不是在整个类或接口中指定。

4. 泛型通配符(Generic Wildcard):

有时,你可能不关心泛型的具体类型,而只想表示它是某个类型的子类。这时可以使用通配符 ?

import java.util.List;

public class GenericWildcardExample {
    
    
    public void processList(List<?> list) {
    
    
        // 处理 list 中的元素,但不关心具体类型
        for (Object item : list) {
    
    
            System.out.println(item);
        }
    }
}

5. 泛型上下界(Generic Bounds):

有时,你希望限制泛型的类型范围,可以使用上下界:

public class GenericBoundsExample {
    
    
    public <T extends Number> void processNumber(T number) {
    
    
        // 处理数字类型的数据
        double square = number.doubleValue() * number.doubleValue();
        System.out.println("Square: " + square);
    }
}

这表示 T 必须是 Number 类型或其子类。

6. 泛型数组(Generic Array):

在 Java 中,创建泛型数组是有限制的,不能直接使用 new T[] 的方式创建泛型数组。通常可以使用 List 来代替。

import java.util.ArrayList;
import java.util.List;

public class GenericArrayExample {
    
    
    public <T> List<T> createGenericList(T... elements) {
    
    
        List<T> list = new ArrayList<>();
        for (T element : elements) {
    
    
            list.add(element);
        }
        return list;
    }

    public static void main(String[] args) {
    
    
        GenericArrayExample example = new GenericArrayExample();
        
        // 创建存储整数的列表
        List<Integer> intList = example.createGenericList(1, 2, 3);
        
        // 创建存储字符串的列表
        List<String> stringList = example.createGenericList("A", "B", "C");
    }
}

总体而言,泛型的使用位置取决于你的需求。在大多数情况下,你可能会在类和方法上使用泛型,以实现更通用和灵活的代码。

猜你喜欢

转载自blog.csdn.net/weixin_74850661/article/details/134385423