2

我有这段代码,无法编译:

import java.util.ArrayList;
import java.util.List;

public class TypeSafetyTest {

    public static void main(String[] args) {
        TypeSafetyTest test = new TypeSafetyTest();
        test.run();
    }

    private void run() {
        Car car = new Car();
        List<String> wheelWeights = car.getWheelWeights();
    }

    private class Car {
        List<Double> wheelWeights = new ArrayList<Double>();

        public List<Double> getWheelWeights() {
            return wheelWeights;
        }

        public void setWheelWeights(List<Double> wheelWeights) {
            this.wheelWeights = wheelWeights;
        }
    }
}

它在行上给出了“不兼容的类型”错误:

List<String> wheelWeights = car.getWheelWeights();

但是,如果我换行:

private class Car {

private class Car<T> {

然后代码成功编译,并在曾经出现编译错误的行上显示警告“未检查的分配”。为什么会这样?我期待它在这两种情况下都会出现编译错误。

4

2 回答 2

3

我看到的一个问题是:

 public List<Double> getWheelWeights() {
            return wheelWeights;
        }

返回Doubletype List,但您将其分配给List<String>

更改时没有看到编译错误的原因Car<T>是,因为您的实例创建是原始类型,这告诉编译器由于向后兼容性而在编译时忽略类型安全。

Car<Object> car = new Car<Object>();

如果您像这样更改您的对象,那么您将看到编译器再次抛出该消息。

请参阅JLS 4.8了解更多信息。

以下是 JLS 的示例:

    class Outer<T>{
        class Inner<S> {
            S s;
        }
    }

Outer.Inner<Double> x = null;  // illegal

不可能将 Inner 作为部分原始类型(“稀有”类型)访问,因为 Outer 本身是原始的,因此它的所有内部类(包括 Inner)也是如此,因此不可能将任何类型参数传递给 Inner

仅允许使用原始类型作为对遗留代码兼容性的让步。强烈反对在将泛型引入 Java 编程语言之后编写的代码中使用原始类型。Java 编程语言的未来版本可能不允许使用原始类型。

我建议阅读泛型(更新)

于 2012-12-04T21:54:55.953 回答
3

当您更改Car为 时Car<T>Car将成为一个泛型类。因此,您的car对象现在具有原始类型Car,因为您没有提供任何类型参数。原始类型的非静态非继承成员也是原始类型。这意味着getWheelWeights()现在返回一个原始类型。而且由于它是原始类型,因此它会进行未经检查的转换,这意味着您只会收到警告,而不是错误。

您可以通过为car. 例如

Car<Object> car = new Car();

请注意,如果您想要泛型的类型安全优势,则根本不应该使用原始类型。它们只是对预通用代码的兼容性修复,因此具有传染性并且缺乏对原始类型的检查。

于 2012-12-04T22:16:41.837 回答