深入学习 Java 泛型的使用方法!

举报
喵手 发表于 2025/03/19 16:26:01 2025/03/19
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  你是否曾经在 Java 开发中,遇到过一个看似无解的问题——你需要一个方法能够处理不同类型的参数,而又不能直接使用 Object 类型?是不是也觉得每次用 Object 类型来处理不同数据类型时,总会有类型转换的问题?别担心!今天我将带你深入学习 Java 泛型的使用方法,帮助你理解泛型的强大之处,让你轻松应对类型安全和灵活性的问题。

一、什么是 Java 泛型?

  Java 泛型(Generics)是 Java 5 引入的一个特性,允许在类、接口和方法中使用类型参数。简单来说,泛型使得你可以在定义类、接口、方法时不指定具体的类型,而是使用占位符(如 TEK 等),具体的类型会在使用时由开发者指定。通过泛型,Java 能够实现类型安全,即使在运行时也能确保数据类型的一致性。

  在没有泛型的情况下,我们只能使用 Object 类型,这样导致了类型不安全和繁琐的类型转换问题。泛型解决了这个问题,它能够让你在编译时检查类型,避免了运行时的错误。

二、Java 泛型的基本使用

1. 泛型类

我们可以在定义类时使用泛型,使得类能处理多种数据类型。比如,我们可以定义一个泛型类来实现一个简单的容器类 Box

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

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

    public T get() {
        return value;
    }

    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>();  // 使用 Integer 类型
        intBox.set(123);
        System.out.println(intBox.get());  // 输出 123

        Box<String> strBox = new Box<>();  // 使用 String 类型
        strBox.set("Hello Generics");
        System.out.println(strBox.get());  // 输出 Hello Generics
    }
}

在这个例子中,我们定义了一个泛型类 Box,其中 T 是类型参数。通过这个类,我们可以创建处理不同数据类型的实例。例如 Box<Integer>Box<String>,它们分别处理 IntegerString 类型的数据。

2. 泛型方法

泛型不仅可以应用在类中,还可以应用在方法中。我们可以定义一个泛型方法,这个方法能够处理不同类型的参数。

// 泛型方法
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[] strArray = {"Java", "Generics", "Example"};

        // 调用泛型方法
        printArray(intArray);  // 输出 1 2 3 4
        printArray(strArray);  // 输出 Java Generics Example
    }
}

在这个例子中,<T> 表示一个类型参数,它可以是任意类型。printArray 方法能够接受任何类型的数组并打印出数组中的每一个元素。当我们调用 printArray 时,Java 会根据传入的参数类型自动推断出泛型类型 T

3. 泛型接口

泛型也可以用于接口的定义。我们可以定义一个泛型接口,指定类型参数,并在实现类中提供具体的类型。

// 泛型接口
interface Pair<K, V> {
    K getKey();
    V getValue();
}

// 实现泛型接口
class ConcretePair<K, V> implements Pair<K, V> {
    private K key;
    private V value;

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

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }

    public static void main(String[] args) {
        Pair<String, Integer> pair = new ConcretePair<>("Age", 30);
        System.out.println(pair.getKey() + ": " + pair.getValue());  // 输出 Age: 30
    }
}

在这个例子中,Pair<K, V> 是一个泛型接口,它有两个类型参数 KV,分别表示键和值。ConcretePairPair 接口的实现类,它提供了 getKeygetValue 方法的具体实现。

三、泛型的边界和限制

1. 上界(Upper Bounded Wildcards)

有时,我们需要限制泛型的类型,确保它属于某个类型的子类或实现了某个接口。这时我们可以使用上界 extends 来进行限制。

// 使用上界来限制泛型类型
public class UpperBoundedWildcardExample {
    // 只接受 Number 或其子类的类型
    public static <T extends Number> void printNumber(T number) {
        System.out.println(number);
    }

    public static void main(String[] args) {
        printNumber(10);   // 输出 10
        printNumber(10.5); // 输出 10.5
    }
}

在这个例子中,<T extends Number> 表示 T 类型必须是 Number 或其子类。这样,我们就确保了只能传入 Number 类型及其子类的数据(例如 IntegerDouble 等)。

2. 下界(Lower Bounded Wildcards)

下界 super 用于限制泛型类型的下界,确保泛型类型是某个类型的父类或该类型本身。

// 使用下界来限制泛型类型
public class LowerBoundedWildcardExample {
    // 只接受 Number 或其父类的类型
    public static void printNumbersList(List<? super Integer> list) {
        for (Object number : list) {
            System.out.println(number);
        }
    }

    public static void main(String[] args) {
        List<Number> numberList = new ArrayList<>();
        numberList.add(10);
        numberList.add(20);

        printNumbersList(numberList);  // 输出 10 20
    }
}

在这个例子中,<? super Integer> 表示列表中的元素类型是 Integer 或其父类(如 NumberObject)。这种类型约束使得我们可以传入 Integer 或其超类型的数据。

3. 无界通配符(Unbounded Wildcards)

有时候,我们希望接受任何类型的对象,这时可以使用无界通配符 <?>

// 使用无界通配符
public class UnboundedWildcardExample {
    public static void printList(List<?> list) {
        for (Object element : list) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        List<String> strList = Arrays.asList("Java", "Generics", "Wildcard");
        List<Integer> intList = Arrays.asList(1, 2, 3);

        printList(strList);  // 输出 Java Generics Wildcard
        printList(intList);  // 输出 1 2 3
    }
}

在这个例子中,<?> 表示可以接受任何类型的列表。printList 方法能够打印任何类型列表的元素,无论是 String 还是 Integer

四、泛型的类型擦除

  Java 中的泛型使用的是类型擦除(Type Erasure)机制。在编译时,Java 会将泛型类型擦除,替换成原始类型(如 ObjectNumber)。这意味着,在运行时,泛型的类型信息已经不存在了。类型擦除可以提高 Java 的兼容性,使得泛型与旧版的非泛型代码能够互相兼容。

例如,泛型类 Box<T> 在编译后,T 会被擦除,变成 Object 类型。这也意味着,不能在运行时获取到泛型的实际类型。

总结

  Java 泛型是一个强大而灵活的特性,它为我们提供了类型安全的同时,也大大提高了代码的可重用性和可维护性。通过泛型,我们能够在编译时就检查类型,避免了类型转换的麻烦,增强了代码的稳定性。

  今天我们介绍了泛型类、泛型方法、泛型接口的基本使用方法,深入探讨了泛型的边界和限制,了解了上界、下界和无界通配符的应用。掌握这些泛型的知识,你将能够写出更加健壮、灵活的代码,提升自己的 Java 编程水平。

  泛型是 Java 编程中的一个基础但强大的工具,掌握好它,将会使你的代码更具可扩展性和可维护性。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。