1. Introduction
1.绪论
In this quick tutorial, we’re going to take a look at raw types, what they are, and why we should avoid them.
在这个快速教程中,我们要看一下原始类型,它们是什么,以及为什么我们应该避免它们。
2. Raw Types
2.原始类型
A raw type is a name for a generic interface or class without its type argument:
原始类型是指没有类型参数的通用接口或类的名称:。
List list = new ArrayList(); // raw type
Instead of:
而不是。
List<Integer> listIntgrs = new ArrayList<>(); // parameterized type
List<Integer> is a parameterized type of interface List<E> while List is a raw type of interface List<E>.
List<Integer>是接口List<E>的一个参数化类型,而List是接口List<E>的一个raw类型。
Raw types can be useful when interfacing with non-generic legacy code.
在与非通用的遗留代码对接时,原始类型可能是有用的。
Otherwise, though, it’s discouraged. This is because:
否则,不鼓励这样做。这是因为。
- They are not expressive
- They lack type safety, and
- Problems are observed at run time and not at compile time
3. Inexpressive
3.不具表达能力
A raw type does not document and explains itself the way a parameterized type does.
一个原始类型不会像参数化类型那样记录和解释自己。
We can easily infer that a parameterized type List<String> is a list that contains Strings. However, a raw type lacks this clarity, making it difficult to work with it and with its API methods.
我们可以很容易地推断出一个参数化的类型List<String>是一个包含String的列表。然而,一个原始类型缺乏这种明确性,使我们很难与它和它的API方法一起工作。
Let’s see the signature of the method get(int index) in the List interface to understand this better:
让我们看看List接口中get(int index)方法的签名,以便更好地理解这个。
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index < 0 || index >= size()</tt>)
*/
E get(int index);
The method get(int index) returns a String at position index in parameterized type List<String>.
方法get(int index)在参数化类型List<String>中返回位置index的一个String。
However, for a raw type List, it returns an Object. Thus, we are required to take extra effort to inspect and identify the type of element in the raw type List and add an appropriate type-casting. This can introduce bugs at run time as raw type is not type safe.
然而,对于原始类型的List,它返回的是Object。因此,我们需要付出额外的努力来检查和识别原始类型List中的元素类型,并添加一个适当的类型转换。这可能会在运行时引入错误,因为原始类型不是类型安全的。
4. Not Type-Safe
4. 不是类型安全的
We get pre-generics behavior with raw types. Therefore, a raw type List accepts Object and can hold an element of any data type. This can lead to type safety issues when we mix parameterized and raw types.
我们通过原始类型得到预生成的行为。因此,原始类型List接受Object,可以容纳任何数据类型的元素。当我们混合使用参数化和原始类型时,这可能会导致类型安全问题。
Let’s see this by creating some code that instantiates a List<String> before passing it to a method that accepts raw type List and adds an Integer to it:
让我们通过创建一些代码来看看,这些代码在将一个List<String>传递给一个接受原始类型List并向其添加一个Integer的方法之前,先将其实例化。
public void methodA() {
List<String> parameterizedList = new ArrayList<>();
parameterizedList.add("Hello Folks");
methodB(parameterizedList);
}
public void methodB(List rawList) { // raw type!
rawList.add(1);
}
The code gets compiled (with a warning), and the Integer gets added to the raw type List when executed. The List<String> that was passed as an argument now contains a String and an Integer.
代码被编译(有警告),执行时Integer被添加到原始类型List。作为参数传递的List<String>现在包含一个String和一个Integer。。
The compiler prints out a warning due to the usage of raw types:
由于使用了原始类型,编译器打印出了一个警告。
Note: RawTypeDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
5. Problems at Runtime
5.运行时的问题
Lack of type safety on a raw type has a causal effect that can lead to exceptions at runtime.
在原始类型上缺乏类型安全,会产生因果效应,在运行时导致异常。
Let’s modify the previous example so that methodA gets the element at index position 1 of our List<String> after calling methodB:
让我们修改前面的例子,使methodA在调用methodB后得到我们的List<String>中索引位置1的元素。
public void methodA() {
List<String> parameterizedList = new ArrayList<>();
parameterizedList.add("Hello Folks");
methodB(parameterizedList);
String s = parameterizedList.get(1);
}
public void methodB(List rawList) {
rawList.add(1);
}
The code gets compiled (with the same warning) and throws a ClassCastException when executed. This happens as the method get(int index) returns an Integer, which cannot be assigned to a variable of type String:
代码被编译(有同样的警告),执行时抛出一个ClassCastException。这是因为方法get(int index)返回一个Integer,它不能被分配给String类型的变量。
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
6. Conclusion
6.结论
Raw types are hard to work with and can introduce bugs in our code.
原始类型是很难处理的,而且会在我们的代码中引入错误。
Using them can lead to consequences that can be disastrous, and unfortunately, most of these disasters happen at run time.
使用它们会导致可能是灾难性的后果,不幸的是,这些灾难大多发生在运行时间。
Check out all the snippets in this tutorial over on GitHub.
请查看本教程中的所有片段在GitHub上。