122. Java 泛型 - 原始类型
1. 什么是原始类型?
原始类型是泛型类或接口的名称,而没有任何类型参数。例如,假设我们有一个泛型类 Box
,它有一个类型参数 T
:
public class Box<T> {
public void set(T t) { /* ... */ }
public T get() { return t; }
}
为了创建 Box<T>
的参数化类型,您需要为类型参数 T
提供一个实际的类型参数:
Box<Integer> intBox = new Box<>();
在这个例子中,Box<Integer>
是参数化类型,意味着 Box
被指定为存储 Integer
类型的数据。
原始类型
如果在声明 Box
时省略了类型参数,则它变成了原始类型。例如:
Box rawBox = new Box();
在这个例子中,Box
被称为泛型类型 Box<T>
的原始类型。注意,原始类型本身并不是泛型类或接口的类型,它只是泛型类名称的一个版本,尚未应用任何类型参数。
非泛型类和接口 并不是原始类型,只有泛型类或接口才有原始类型的概念。
原始类型的行为
当使用原始类型时,代码会表现出类似于泛型未引入之前的行为。举个例子,原始类型的 Box
会退化为 Object
类型,允许存储任何类型的数据,这也意味着你将失去类型安全的好处。
例如:
Box rawBox = new Box(); // 使用原始类型
Box<String> stringBox = new Box<>();
rawBox = stringBox; // 允许这样做
在这段代码中,Box<String>
被赋值给原始类型的 rawBox
,是允许的,因为原始类型在编译时不进行类型检查。
原始类型的警告
然而,问题出现在将原始类型分配给具体类型时,编译器会发出警告。比如:
Box rawBox = new Box(); // 原始类型 Box<T>
Box<Integer> intBox = rawBox; // 警告: 未检查转换
这段代码的 rawBox
是一个原始类型,赋值给 Box<Integer>
时,编译器会发出警告:未检查的转换。
如果尝试使用原始类型调用泛型方法,也会出现警告,例如:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // 警告: 未检查的方法调用
在这段代码中,rawBox.set(8)
是一个未经检查的操作,编译器发出警告,表示您绕过了类型检查,可能导致类型不安全的问题。
因此,强烈建议避免使用原始类型。
2. 未选中的警告消息
当将旧代码与泛型代码混合时,可能会遇到类似以下的警告:
Note: Example.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
这种警告通常出现在混合使用原始类型和泛型类型时。例如:
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
static Box createBox(){
return new Box(); // 使用原始类型
}
}
在这个示例中,createBox()
返回一个原始类型的 Box
,并且赋值给了 Box<Integer>
类型的变量 bi
,编译器无法确定类型安全性,因此给出了 unchecked
警告。
如何查看未选中的警告?
默认情况下,unchecked
警告是禁用的,编译器会提示“未选中的操作”。要查看所有未选中的警告,可以使用 -Xlint:unchecked
重新编译代码:
javac -Xlint:unchecked WarningDemo.java
这样会显示更详细的警告信息,例如:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
如何禁用未选中的警告?
如果希望禁用所有未选中的警告,可以使用 -Xlint:-unchecked
标志:
javac -Xlint:-unchecked WarningDemo.java
如果您希望在代码中禁用特定的方法或类的警告,可以使用 @SuppressWarnings("unchecked")
注解:
@SuppressWarnings("unchecked")
public void someMethod() {
// Some code that causes unchecked warnings
}
这会禁止显示“未选中的操作”的警告,但请注意,@SuppressWarnings
应谨慎使用,因为它可能掩盖潜在的类型安全问题。