Java “为什么;“不兼容类型”;当类被设置为泛型时,编译错误会变成警告吗?

Java “为什么;“不兼容类型”;当类被设置为泛型时,编译错误会变成警告吗?,java,generics,Java,Generics,我有一段代码,无法编译: 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() {

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

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;
        }
    }
}

私家车{
然后,代码成功编译,在曾经出现编译错误的行上出现警告“Unchecked assignment”。为什么会这样?我希望它在这两种情况下都会出现编译错误。

我看到的一个问题是:

 public List<Double> getWheelWeights() {
            return wheelWeights;
        }
如果像这样更改对象,则会看到编译器再次抛出消息

有关更多信息,请参阅

以下是JLS的示例:

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

Outer.Inner<Double> x = null;  // illegal
类外部{
班级内部{
S S;
}
}
Outer.Inner x=null;//非法
不可能作为部分原始类型(一种“罕见”类型)访问内部,因为外部本身是原始的,因此包括内部在内的所有内部类也是原始的,因此不可能将任何类型参数传递给内部

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


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

您可以通过为
car
提供类型参数来解决此问题

Car<Object> car = new Car();
Car-Car=新车();

请注意,如果您想获得泛型的类型安全好处,就不应该使用原始类型。它们只是预泛型代码的兼容性修复程序,因此具有传染性,并且没有检查原始类型。

他知道这一点。他在问,为什么在使用参数化类型时,它没有给出错误。我的答案纯粹是一个有根据的猜测。我figure您可以给出一个更正确的答案。我明白了。如果编译器真的忽略了类型安全性,因为Car对象没有用类型初始化,那么我希望编译器只忽略Car中实际使用类型声明的字段的类型安全性。@Thomas Raw类型基本上是遗留代码的兼容性度量,因此很少应用类型检查。@ThomasRyabin:原始类型是为了方便与非泛型遗留代码进行接口,您在那里收到的警告消息告诉您,如果您希望在编译时实现类型安全,请确保始终遵守泛型。@ThomasRyabin:这是一个常见的误解。但Java l语言是指定的。原始类型应该只用于与泛型前代码的兼容性——出于这个原因,任何其他的使用几乎都是错误的。试图理解Java泛型只会导致疯狂。我一直在浏览Java语言规范,但仍然无法找到这个问题的答案。不是dup简单但密切相关:基本上,一旦您使用原始类型声明类,您就明确地选择了整个类的所有泛型。您的“修复”仍然会导致未检查的转换警告,因为右侧仍然是原始类型(但至少不会更改
car
变量的用法)。最好在两侧都指定类型参数,如:
Car Car=new Car();
@Daniel Good point。我只是想在make the compiler error return中“fix”,但您是对的,最好在两侧都使用类型参数。
 public List<Double> getWheelWeights() {
            return wheelWeights;
        }
Car<Object> car = new Car<Object>();
    class Outer<T>{
        class Inner<S> {
            S s;
        }
    }

Outer.Inner<Double> x = null;  // illegal
Car<Object> car = new Car();