java泛型介绍(Java泛型机制详解)(1)

一、Java 中为什么会引入泛型?

Java 引入泛型的主要目的是为了提高代码的类型安全性和可读性。在 Java 5 之前,集合框架中的容器可以存储任意类型的对象,这就使得程序员需要在运行时进行类型转换,容易引发类型转换异常。而引入泛型后,集合框架中的容器可以限定存储的元素类型,使得程序员可以在编译时进行类型检查,避免了类型转换异常的发生。此外,泛型还可以提高代码的可读性和可维护性,使得代码更易于理解和修改。泛型的引入使得 Java 语言更加类型安全,更加适合大规模软件开发。

接下来我们举个例子说明为什么: 假设有一个需求,需要编写一个方法,用于比较两个对象是否相等。最初的实现可能是这样的。

java复制代码public static boolean compareObject(String s1, String s2) { return s1.equals(s2); }

但是入参不一定是 String,也有可能是 int、long 等,那么该怎么写呢?难道每个都写一遍?

java复制代码public static boolean compareObject(String s1, String s2) { return s1.equals(s2); } public static boolean compareObject(Integer s1, Integer s2) { return s1.equals(s2); }

这样的代码可读性,可维护性都很差,于是我们用泛型进行改进, 一个方法就搞定了。

java复制代码public static <T> boolean compareObjects(T o1, T o2) { return o1.equals(o2); }

二、泛型的应用

泛型是 Java 中的一个重要特性,它可以让我们编写更加通用、可复用的代码。

java复制代码package com.pany.camp.base; public class Genericity<T, U> { private T first; private U second; public Genericity(T first, U second) { this.first = first; this.second = second; } public T getFirst() { return first; } public U getSecond() { return second; } public void setFirst(T first) { this.first = first; } public void setSecond(U second) { this.second = second; } @Override public String toString() { return "(" first ", " second ")"; } }

这个示例中定义了一个泛型类 Genericity,它有两个类型参数 T 和 U,分别表示 Genericity 中的两个元素的类型。Genericity类有一个构造函数,用于初始化 Genericity对象的两个元素。Genericity 类还有一些方法,用于获取和设置 Genericity 对象的元素,以及将 Genericity 对象转换成字符串表示。

java复制代码package com.pany.camp.base; public class GenericityMain { public static void main(String[] args) { Genericity<String, Integer> pair = new Genericity<>("Hello", 123); // 输出:(Hello, 123) System.out.println(Pair); } }

java泛型介绍(Java泛型机制详解)(2)

它的第一个元素是一个字符串,第二个元素是一个整数。使用泛型可以让我们编写更加通用、可复用的代码,可以在不同的场景中使用相同的类来处理不同类型的数据。

三、泛型接口

java复制代码package com.pany.camp.base; public interface Pair<T, U> { T getFirst(); U getSecond(); }

我们定义了一个泛型接口 Pair,它有两个类型参数 T 和 U,分别表示 Pair 中的两个元素的类型。Pair 接口有两个方法,getFirst() 和 getSecond(),用于获取 Pair 对象的两个元素。

java复制代码package com.pany.camp.base; public class StringIntegerPair implements Pair<String, Integer> { private String first; private Integer second; public StringIntegerPair(String first, Integer second) { this.first = first; this.second = second; } @Override public String getFirst() { return first; } @Override public Integer getSecond() { return second; } }

然后我们创建了一个 StringIntegerPair 类,它实现了 Pair 接口,并指定了 T 和 U 的具体类型为 String 和 Integer。StringIntegerPair 类有一个构造函数,用于初始化 StringIntegerPair 对象的两个元素。StringIntegerPair 类还实现了 Pair 接口的两个方法,用于获取 StringIntegerPair 对象的两个元素。

四、泛型方法

泛型方法可以让我们编写更加通用、可复用的代码,可以在不同的场景中使用相同的方法来处理不同类型的数据。

例子如下:

bash复制代码public static <T> int countOccurrences(T[] array, T element) { int count = 0; for (T value : array) { if (value.equals(element)) { count ; } } return count; }

我们定义了一个泛型方法 countOccurrences,它有两个参数,一个是泛型类型数组 array,另一个是泛型类型元素 element。countOccurrences 方法的作用是统计数组中与 element 相等的元素个数。

bash复制代码String[] strings = {"foo", "bar", "baz", "foo"}; int count1 = countOccurrences(strings, "foo"); // 返回 2 int count2 = countOccurrences(strings, "qux"); // 返回 0 Integer[] integers = {1, 2, 3, 2, 1}; int count3 = countOccurrences(integers, 2); // 返回 2 int count4 = countOccurrences(integers, 4); // 返回 0

我们分别使用了字符串类型数组和整数类型数组来调用 countOccurrences 方法,传入不同的元素来统计数组中相等的元素个数。

五、泛型的上下限

泛型的上下限是指在使用泛型时,可以限制泛型参数的类型范围,从而提高代码的类型安全性。上限限制了泛型参数的类型必须是某个类或其子类,下限限制了泛型参数的类型必须是某个类或其父类。 使用泛型的上下限可以避免类型转换错误,提高代码的类型安全性。

在 Java 中,可以使用 extends 关键字来指定泛型的上限,使用 super 关键字来指定泛型的下限。例如:

bash复制代码public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } } // 使用 extends 指定泛型的上限 public class NumberBox<T extends Number> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } } // 使用 super 指定泛型的下限 public class IntegerBox<T super Integer> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } }

NumberBox 类使用 extends 指定泛型参数的上限为 Number 类型及其子类,因此只能使用 Number 类型及其子类作为泛型参数。而 IntegerBox 类使用 super 指定泛型参数的下限为 Integer 类型及其父类,因此只能使用 Integer 类型及其父类作为泛型参数。

作者:激流丶链接:https://juejin.cn/post/7241765112921735227

,