The Java™ Tutorials — Generics :Raw Types 原始类型
原文地址:https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html
关键点
- 定义:
- 缺少实际类型变量的泛型就是一个原始类型
- 举例:
class Box<T>{}
Box b = new Box(); //这个Box就是Box<T>的原始类型
- 实际行为:获取和返回的类型都为Object
- 缺点:无法进行编译时类型检查,将异常的捕获推迟到了运行时,还可能会收到unchecked警告。
- 对unchecked警告的处理
全文翻译
A raw type is the name of a generic class or interface without any type arguments. For example, given the generic Box class:
如果一个泛型类或泛型接口不具有任何类型变量,那么我们就称其为原始类型。例如下面给出的泛型BOX类:
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
To create a parameterized type of
Box<T>
, you supply an actual type argument for the formal type parameter T:
为了提供一个参数化类型的Box<T>
,你应该为正式类型参数T提供一个真正的类型变量:
Box<Integer> intBox = new Box<>();
If the actual type argument is omitted, you create a raw type of
Box<T>
:
如果省去了真正的类型变量,你就创建了一个原始类型的Box<T>
。
Box rawBox = new Box();
Therefore, Box is the raw type of the generic type
Box<T>
. However, a non-generic class or interface type is not a raw type.
因此,Box就是泛型Box<T>
的原始类型。然而,一个非泛型类或接口就不是一个原始类型。
Raw types show up in legacy code because lots of API classes (such as the Collections classes) were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics behavior — a Box gives you Objects. For backward compatibility, assigning a parameterized type to its raw type is allowed:
原始类型在老代码中十分常见。因为很多API类(如集合类)在JDK 5.0之前并不支持泛型。当用原始类型时,你本质上就会获得使用泛型前的行为——Box会给你返回Object类型。对于向后兼容的问题,将它的一个参数化类型赋值给它的原始类型是可以的。
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK
But if you assign a raw type to a parameterized type, you get a warning:
但是如果你把一个原始类型赋值给一个参数化类型时,你就会得到一个警告:
Box rawBox = new Box(); // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox; // warning: unchecked conversion
You also get a warning if you use a raw type to invoke generic methods defined in the corresponding generic type:
如果你使用一个原始类型调用一个泛型方法,而这个泛型方法定义在对应的泛型中时,你也会收到一个警告:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)
The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types.
这个警告表明原始类型绕过了泛型检查,将对不安全代码的异常捕获推迟到了运行时。因此,你应该避免使用原始类型。
The Type Erasure section has more information on how the Java compiler uses raw types.
关于Java编译器如何使用原始类型的更多信息,请参阅《类型消除》一章
Unchecked Error Messages “未检查”错误信息
As mentioned previously, when mixing legacy code with generic code, you may encounter warning messages similar to the following:
如上所述,当你将老代码和使用了泛型的代码混着使用的时候,你就可能遇到和下面类似的警告信息:
Note: Example.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
This can happen when using an older API that operates on raw types, as shown in the following example:
在使用一个利用原始类型操作的老版本API时(例如下面的例子),也可能出现上面的警告信息:
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
static Box createBox(){
return new Box();
}
}
The term “unchecked” means that the compiler does not have enough type information to perform all type checks necessary to ensure type safety. The “unchecked” warning is disabled, by default, though the compiler gives a hint. To see all “unchecked” warnings, recompile with -Xlint:unchecked.
词条“未检查”表明编译器并没有足有的信息去执行所有的类型检查,而这些检查对于保持类型安全是必要的。虽然编译器给出了提示,但这个”未检查”的警告在默认情况下是关闭的。如果希望查看所有的未检查警告,利用 -Xlint:unchecked 重新编译代码
Recompiling the previous example with -Xlint:unchecked reveals the following additional information:
利用此选项重新编译之前例子后,就会显示出下面的这些额外信息:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
To completely disable unchecked warnings, use the -Xlint:-unchecked flag. The @SuppressWarnings(“unchecked”) annotation suppresses unchecked warnings. If you are unfamiliar with the @SuppressWarnings syntax, see Annotations.
为了完全禁用“未检查”警告,你需要使用选项-Xlint:-unchecked
。这个@SuppressWarnings("unchecked")
注释会抑制“未检查”警告。如果你对这个注释语法不了解,请参阅《注释》一章。