Java 泛型提供了强大的泛型机制,可以在编译时检查类型安全,并且可以编写通用的代码,使得代码更加灵活和重用。除了基本的泛型用法外,还有一些高级的泛型用法,以下是一些常见的高级泛型用法:
-
泛型通配符(Wildcard):通配符用于表示未知类型,可以增加泛型的灵活性。主要包括上界通配符
<? extends T>
和下界通配符<? super T>
。通配符可以用在泛型类、方法、接口等地方。 -
泛型方法:泛型方法是在方法声明时定义泛型类型,而不是在类定义时。可以让方法根据调用时的参数类型来确定返回类型,增加方法的灵活性。
-
泛型接口:类似于泛型类,泛型接口可以定义一种通用类型,可以在接口的方法中使用泛型类型。
-
泛型类的继承:泛型类也可以进行继承,子类可以继承父类的泛型类型,并可以添加自己的泛型类型。
-
泛型限定和约束:可以使用
extends
和super
关键字来限定泛型的范围,用于实现更灵活的泛型类型限定和约束。 -
泛型擦除与反射:在运行时,Java 的泛型信息会被擦除,这就导致了泛型类型不能通过反射获取泛型信息。但是可以通过获取父类(ParameterizedType)来获取泛型信息。
当使用泛型时,虽然在运行时泛型信息会被擦除,但是可以通过获取父类(ParameterizedType)来获取泛型信息。以下是一个示例代码演示如何通过获取父类来获取泛型信息:
可以通过使用匿名类来实现。以下是一个示例代码:
package org.example.gstjava.pojo;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* 一个泛型类的示例,包含两个泛型参数 T 和 U。
*/
class GenericClass<T,U> {}
public class Main {
/**
* 主函数:演示如何通过反射获取匿名泛型类的泛型参数类型。
* @param args 命令行参数(未使用)
*/
public static void main(String[] args) {
// 创建一个匿名泛型类实例,继承自 GenericClass<String,Integer>
GenericClass<String,Integer> generic = new GenericClass<String,Integer>() {};
// 获取匿名类的泛型超类类型
Type genericSuperclass = generic.getClass().getGenericSuperclass();
// 检查获取的类型是否为参数化类型
if (genericSuperclass instanceof ParameterizedType) {
// 将泛型超类类型转为 ParameterizedType 接口实例,以便访问其参数
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
// 获取实际的泛型参数类型数组
Type[] typeArguments = parameterizedType.getActualTypeArguments();
// 遍历并打印所有泛型参数的类型名称
if (typeArguments.length > 0) {
for(Type type:typeArguments){
System.out.println("Type: " + type.getTypeName());
}
} else {
// 如果没有泛型参数,打印相应信息
System.out.println("Type: No type arguments");
}
} else {
// 如果获取的类型不是参数化类型,打印相应信息
System.out.println("Type: Not a parameterized type.");
}
}
}
在示例中,我们使用了匿名类 new GenericClass<String>() {}
来创建 GenericClass
的实例,这样我们就可以通过 getClass().getGenericSuperclass()
获取到超类的 ParameterizedType
。这样可以确保 typeArguments.length
大于0,从而使 if (typeArguments.length > 0)
这个条件成立。希望这个示例能够满足您的要求。如果有任何问题,请随时告诉我。
-
泛型数组:在 Java 中创建泛型数组是不合法的,但是可以使用通配符或 Array.newInstance() 方法来创建泛型数组。
-
泛型类型推断:在 Java 7 中引入了钻石操作符
<>
,可以省略泛型类型的声明,编译器会根据上下文自动推断泛型类型。
这些是一些常见的高级泛型用法,通过灵活运用泛型机制,可以使代码更加通用和安全。在实际开发中,合理利用泛型能够提高代码的质量和扩展性。
以下是针对上述8个高级泛型用法的示
例代码:
- 泛型通配符(Wildcard):
public void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
}
- 泛型方法:
public <T> T add(T a, T b) {
return a + b; //这里仅作举例,实际上加法不适用于泛型,应该改用其他方式
}
- 泛型接口:
interface MyInterface<T> {
void doSomething(T item);
}
- 泛型类的继承:
class GenericClass<T> {
T value;
}
class SubClass<T> extends GenericClass<T> {
// 子类可以继承父类的泛型类型
}
- 泛型限定和约束:
public <T extends Number> void processNumber(T number) {
// 只能传入 Number 及其子类
}
- 泛型擦除与反射:
class MyClass<T> {
private Class<T> type;
public MyClass(Class<T> type) {
this.type = type;
}
}
MyClass<String> myObject = new MyClass<>(String.class);
- 泛型数组:
List<?>[] arrayOfLists = new List<?>[2];
arrayOfLists[0] = new ArrayList<>();
arrayOfLists[1] = new LinkedList<>();
- 泛型类型推断:
List<String> list = new ArrayList<>(); // 使用了钻石操作符
import java.util.*;
public class Main {
public static void main(String[] args) {
// 泛型通配符示例
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("World");
printList(stringList);
// 泛型方法示例
Integer sum = add(10, 20);
System.out.println("Sum: " + sum);
// 泛型接口示例
MyInterface<String> myInterface = new MyImplementation<>();
myInterface.doSomething("Generic Interface");
// 泛型类的继承示例
SubClass<Integer> subClass = new SubClass<>();
subClass.value = 100;
System.out.println("Value: " + subClass.value);
// 泛型限定和约束示例
processNumber(10);
// 泛型擦除与反射示例
MyClass<String> myObject = new MyClass<>(String.class);
System.out.println("Type: " + myObject.type.getName());
// 泛型数组示例
List<?>[] arrayOfLists = new List<?>[2];
arrayOfLists[0] = new ArrayList<>();
arrayOfLists[1] = new LinkedList<>();
System.out.println("Array Size: " + arrayOfLists.length);
// 泛型类型推断示例
List<String> list = new ArrayList<>();
list.add("Java Generics");
System.out.println("List: " + list.get(0));
}
public static void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
}
public static <T> T add(T a, T b) {
return a; // 这里仅作举例
}
interface MyInterface<T> {
void doSomething(T item);
}
static class MyImplementation<T> implements MyInterface<T> {
@Override
public void doSomething(T item) {
System.out.println("Doing something with: " + item);
}
}
static class GenericClass<T> {
T value;
}
static class SubClass<T> extends GenericClass<T> {
// 子类可以继承父类的泛型类型
}
public static <T extends Number> void processNumber(T number) {
System.out.println("Number is: " + number);
}
static class MyClass<T> {
private Class<T> type;
public MyClass(Class<T> type) {
this.type = type;
}
}
}