Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 编译器不';当使用具有多个边界的泛型时,不能打印编译时错误_Java_Generics_Compiler Errors - Fatal编程技术网

Java 编译器不';当使用具有多个边界的泛型时,不能打印编译时错误

Java 编译器不';当使用具有多个边界的泛型时,不能打印编译时错误,java,generics,compiler-errors,Java,Generics,Compiler Errors,我试图理解为什么编译器没有在下面的代码中打印编译时错误。它可以编译,但显然不起作用 有人知道编译器为什么允许它吗 public class Tests { public static void main(String... args){ // Lines below are acceptable for the compiler and work well in runtime. GenericClass<FooClassWithFooInterfa

我试图理解为什么编译器没有在下面的代码中打印编译时错误。它可以编译,但显然不起作用

有人知道编译器为什么允许它吗

public class Tests {
    public static void main(String... args){
        // Lines below are acceptable for the compiler and work well in runtime.
        GenericClass<FooClassWithFooInterface> genericClass1 = new GenericClass();
        genericClass1.print(new FooClassWithFooInterface());

        // Lines below are oddly acceptable for the compiler and, obviously, won't work in runtime.
        GenericClass genericClass2 = new GenericClass();
        genericClass2.print(new FooClassWithFooInterface());
        genericClass2.print(new FooClass()); // why the compiler not throw a compile-time error?
    }
}


class GenericClass<T extends FooClass & FooInterface>{
    public void print(T t){
        t.fooMethod();
    }
}

class FooClass{

}

interface FooInterface{
    public void fooMethod();
}

class FooClassWithFooInterface extends FooClass implements FooInterface{
    @Override
    public void fooMethod() {
        System.out.println("foo");
    }   
}
我创建fooMethod()只是为了强制执行此运行时错误


我认为编译器可以检查
new FooClass()
不匹配。当您使用多个边界时,在编译时类型擦除之后,第一个边界将保留在类型签名中。根据后续边界的需要插入强制类型转换。因此,如果您查看编译的
GenericClass
,您将看到如下内容

class GenericClass {
    public void print(FooClass t){
        ((FooInterface) t).fooMethod();
    }
}
因为编译器看到
GenericClass
有一个
print(FooClass)
方法,所以它不会抱怨。但在运行时,方法内部的强制转换失败

为什么编译器允许这样做,而人类可以推断这注定会失败?嗯,编译器没有你聪明。只有当您限制自己使用类型安全代码时,它才能发现问题,这意味着永远不要使用原始类型或抑制类型警告


还有两种情况,一个人在查看上下文时,可以推断其他操作是安全的,但编译器会抱怨。编译器只使用声明的信息,一次只查看一个表达式;它不考虑泛型类型的整个上下文。

您明确地告诉编译器不要在这里检查类型:

GenericClass genericClass2 = new GenericClass();
通过省略泛型类型参数,您将强制编译器进入遗留模式(它是为java prioer编写的代码,使用JDK5+进行5次编译)。如果未给出泛型类型参数,则会收到警告,并且编译器会接受泛型类型的任何类型


所以基本上你是在自食其果,现在抱怨编译器在明确告诉他闭嘴后没有阻止你:)

你收到编译器警告了吗?看起来你在做不安全的任务。因为你在使用原始类型。不要。看,我收到了警告。但不是错误。我认为编译器可以检查
new FooClass()
是否与
不匹配,Java将允许您执行会出现警告的失败操作。这就是警告的目的。重要的一点是,像
GenericClass
这样的原始类型并不等同于
GenericClass相同的答案,但在没有解释的情况下获得了2次否决票:D
class GenericClass {
    public void print(FooClass t){
        ((FooInterface) t).fooMethod();
    }
}
GenericClass genericClass2 = new GenericClass();