Java基础 —— 泛型(三)
泛型方法
泛型方法是指在方法中使用泛型类型参数的方法,它可以在方法调用时确定类型参数的类型。在 Java 中,我们可以使用以下语法定义泛型方法:
import java.util.ArrayList;
public class GenericMethodDemo {
//<T> - 泛型类型参数,类型参数是一个占位符,它表示一个未知的类型,
//这个未知的类型将在方法调用时由实际参数类型来确定。
public <T> void methodName(T arg) {
// method implementation
}
public <T> T valueMethodName(T arg) {
// method implementation
return arg;
}
public <T> void printList(ArrayList<T> list) {
for (T item : list) {
System.out.println(item);
}
}
//对比原始写法
public void printList2(ArrayList list) {
for (Object obj : list) {
System.out.println(obj);
}
}
}
表示泛型类型参数,T 是类型参数的名称,它可以是任何有效的 Java 标识符。在方法调用时,我们可以通过传递参数来确定类型参数的类型,例如:
GenericMethodDemo gmd = new GenericMethodDemo();
gmd.methodName("string");
gmd.methodName(123);
gmd.methodName(newArrayList<String>());
在这些方法调用中,类型参数 T 的类型分别是 String、Integer 和 ArrayList 。
除了在方法参数中使用泛型类型参数,我们还可以在方法的返回值类型中使用泛型类型参数,如class GenericMethodDemo中的valueMethodName()方法:
public <T> T valueMethodName(T arg) {
// method implementation
return arg;
}
上面的方法的返回值类型为泛型类型参数 T。
泛型接口
泛型接口是一种使用类型参数的接口。下面是一个简单的例子:
public interface MyInterface<T> {
T getValue();
void setValue(T value);
}
public class MyClass implements MyInterface<Integer> {
private Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
复杂一点的例子:
public interface Pair<K, V> {
K getKey();
V getValue();
void setKey(K key);
void setValue(V value);
}
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;
}
public void setKey(K key) {
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
}
调用:
Pair<String, Integer> p1 = new OrderedPair<>("One", 1);
Pair<String, String> p2 = new OrderedPair<>("Hello", "World");
泛型数组
Java 中是不允许创建泛型数组的,即无法使用 new T[] 的方式创建泛型数组,因为 Java 中的泛型是在编译时实现类型擦除的,即将所有泛型类型参数擦除为它们的上界类型(或 Object 类型)。这意味着,在运行时,无法获取泛型类型参数的实际类型,从而无法创建泛型数组。
但是,我们可以使用类型擦除后的类型创建泛型数组,然后将其转换为泛型类型。例如,我们可以使用以下方式创建一个 ArrayList 对象:
ArrayList<Integer> list = new ArrayList<>();
在 Java 中,由于类型擦除的限制,我们通常不能直接创建泛型数组,但有时候我们可以使用一些技巧来创建泛型数组。
例如,如果我们需要创建一个泛型数组,可以先创建一个 Object 数组,然后将其转换为泛型数组。这里有一个示例:
public class GenericArray<T> {
private T[] arr;
public GenericArray(int size) {
arr = (T[]) new Object[size];
}
public T get(int index) {
return arr[index];
}
public void set(int index, T value) {
arr[index] = value;
}
public static void main(String[] args) {
GenericArray<Integer> array = new GenericArray<>(10);
array.set(0, 1);
array.set(1, 2);
System.out.println(array.get(0));
System.out.println(array.get(1));
}
}
在上面的代码中,我们先创建了一个 Object 类型的数组,然后将其转换为泛型数组。由于类型擦除的原因,这里的泛型类型参数 T 将被擦除为 Object 类型。虽然我们可以使用这种方法创建泛型数组,但是需要注意的是,这种方法可能会导致 ClassCastException 异常。因此,我们应该谨慎使用这种方法,尽量避免出现这种异常。
总结
泛型方法:可以在方法中定义泛型类型参数,从而使方法能够处理不同类型的数据。泛型方法的语法格式为: 返回值类型 方法名(参数列表)。
泛型接口:可以在接口中定义泛型类型参数,从而使接口能够处理不同类型的数据。泛型接口的语法格式为:interface 接口名 { ... }。
泛型数组:在 Java 中,由于类型擦除的限制,我们通常不能直接创建泛型数组,但可以使用一些技巧来创建泛型数组。一种常用的方法是先创建一个 Object 数组,然后将其转换为泛型数组。
再补充一下几个常见的泛型使用场景:
集合框架:Java 集合框架中的各种集合类(如 ArrayList、HashMap 等)都使用了泛型来保证类型安全和灵活性,使得集合类能够存储和操作不同类型的数据。
泛型 DAO:在 DAO 层中,我们通常需要实现许多相似的操作(如查询、添加、更新、删除等),如果每个实体类都要写一套 CRUD 操作的代码,会显得非常冗余和重复。利用泛型可以轻松实现通用的 DAO 接口和实现类,使得不同的实体类都能够使用同一套 CRUD 操作的代码。
泛型方法:在编写通用的工具类或者算法时,我们常常需要编写一些通用的方法来处理不同类型的数据。利用泛型方法可以轻松实现这些通用的方法,使得代码更加灵活和通用。
异常类:有时候我们需要定义一些通用的异常类来处理不同类型的异常,这时候就可以使用泛型来定义通用的异常类,从而使得代码更加简洁和通用。
本文只是个人(EnergyNo8)学习笔记如有错误请网友指出。
如有引用或转载请标明出处!
努力、坚持,总会有收获!
______ EnergyNo8