[Java]边界类型和静态字段访问
在 Java 的泛型中,边界类型是用来限制泛型参数的类型范围的。 首先,我们定义两个类,它们都有一个静态字段
public class Parent {
public static final String FIELD = "Parent";
}
public class Child extends Parent {
public static final String FIELD = "Child";
}
然后,我们定义一个泛型类,它尝试访问泛型参数的静态字段:
public class Container<T extends Parent> {
public void printField() {
System.out.println(T.FIELD);
}
}
如果我们创建一个 Container 的实例,它的泛型参数是 Child,然后调用 printField 方法,它会打印"Parent",而不是"Child"
Container<Child> container = new Container<>();
container.printField(); // 输出"Parent"
这是因为在运行时,泛型参数 T 被擦除为它的边界类型 Parent,所以 T.FIELD 实际上是 Parent.FIELD。 如果我们需要访问 Child 的 FIELD 字段,我们应该直接访问它,而不是通过泛型参数来访问:
public class Container<T extends Parent> {
public void printField() {
System.out.println(Child.FIELD);
}
}
现在,我们调用 printField 方法,它会打印"Child":
Container<Child> container = new Container<>();
container.printField(); // 输出"Child"
如果我们需要在 Container 类中根据泛型参数的实际类型做不同的处理,我们可以使用 instanceof 操作符来检查泛型参数的实际类型,然后根据实际类型做不同的处理。
public class Container<T extends Parent> {
public void printField(T instance) {
if (instance instanceof Child) {
System.out.println(Child.FIELD);
} else {
System.out.println(Parent.FIELD);
}
}
}
现在,如果我们传递一个实例给 printField 方法:
Container<Parent> container = new Container<>();
container.printField(new Child()); // 输出"Child"
container.printField(new Parent()); // 输出"Parent"
总结
由于 Java 的类型擦除机制,泛型参数的实际类型在运行时是不可知的。在运行时,所有的泛型参数都会被擦除为它们的边界类型。
- 不要在泛型类或方法中访问泛型参数的静态字段或方法。因为在运行时,泛型参数的静态字段或方法实际上是它的边界类型的静态字段或方法。
- 如果你需要访问一个特定类型的静态字段或方法,你应该直接访问它,而不是通过泛型参数来访问。
- 如果你需要在泛型类或方法中根据泛型参数的实际类型做不同的处理,你可以使用 instanceof 操作符来检查泛型参数的实际类型,然后根据实际类型做不同的处理。