下面的代码没有在OpenjDK 11上编译。在我看来,B中的test1应该覆盖A中的test1,因为:
我使用了一个反编译器,分别对每个类进行反编译。编译后的代码实际上像我期望的那样工作。它用数字代替U扩展数字,用整数代替T扩展整数,以此类推。但当我试图将这两个类一起编译时,第二个类出现了一个错误,即第二个类中的测试没有覆盖第一个类中的方法。
我错过了一些大大小小的东西。它可能与5有关。也许类型不是协变的。你能帮帮我吗?
class A {
<U extends Number, T extends Number> U test(T test) {
System.out.println("In A.test(T test)");
return null;
}
//Decompiler shows that the above method erases to
// Number test(Number test)
// Just like the method below.
Number test2(Number test) {
return null;
}
}
class B extends A {
//Unsuccessful override. Compiler error.
@Override
<U extends Integer, T extends Number> U test(T test) {
System.out.println("In B.test(T tesT)");
return null;
}
//Decompiler shows that the above method erases to
//Integer test(Number test)
//Just like the method bellow.
//Successful override
@Override
Integer test2(Number test) {
return null;
}
}
test
方法产生错误的原因是它们具有不同的签名。请注意,方法的签名由其名称、参数列表和类型参数组成。
引用Java语言规范:
两个方法或构造函数,M和N,如果具有相同的名称、相同的类型参数(如果有的话),则具有相同的签名(§8.4.4),并且,在将N的形式参数类型适应M的类型参数之后,具有相同的形式参数类型。
至关重要的是,您的两个test
方法没有相同的类型参数,因为A. test
中的U
与B. test
中的U
有不同的绑定。
两个方法或构造函数M和N具有相同的类型参数,如果以下两个都是true:
>
M和N具有相同数量的类型参数(可能为零)。
其中A1。。。,An是M和B1的类型参数。。。,Bn是N的类型参数,设θ=[B1:=A1,…,Bn:=An]。那么,尽管我(1≤ 我≤ n) ,Ai的界与应用于Bi的界的θ的类型相同。
想想如果B. test
实际上覆盖了A. test
会发生什么。您可以将类型传递给超出其边界的类型参数U
!
A a = new B();
// This will call B.test, and U is Double, T is Integer
// but U should extends Integer!
Double x = a.test((Integer)0);
无法编译以下内容: 特别是,使用javac编译时,错误将是: 但下面的汇编很好: 唯一的区别是我引入了一个额外的变量。请注意,我没有施法,所以没有语义变化。 有人能解释为什么需要这样做吗?
问题内容: 我偶然发现该语句(从一些更复杂的代码中摘录)进行编译: 在短暂但快乐的时刻,我认为受检查的异常最终决定已经死亡,但是对此仍然感到遗憾: 该块不必为空;似乎可以有代码,只要该代码不引发检查异常即可。这似乎是合理的,但是我的问题是,语言规范中的哪个规则描述了此行为?据我所知,§14.18throw语句明确禁止使用它,因为表达式的类型是已检查的异常,并且不会被捕获或声明为被抛出。(?) 问题
根据Java教程 将包装类型(整数)的对象转换为其相应的基元(int)值称为取消装箱。当包装类的对象为: 作为参数传递给需要相应基元类型的值的方法 分配给相应基元类型的变量 为什么在这种情况下会发生拆箱? 在这种情况下,这些事情发生在哪里?是否有管理数组中元素访问的底层方法?或者[]暗示某种变量?
问题内容: 我编写了以下代码来实现Singleton模式: 当我编译此文件时,它应该生成Test.class和Test $ TestHolder.class,但它还会生成Test $ 1.class。这没有道理。那么,为什么以及如何呢? 问题答案: 类需要在中调用私有构造函数。但是它是私有的,实际上不能从另一个类中调用。因此,编译器发挥了作用。它 添加了一个仅知道的新的非私有构造函数!_该构造函数
问题内容: 我以为Java擦除会在编译时消除泛型类型,但是当我自己对其进行测试时,我意识到在Bytecode中有一些有关泛型类型的信息。 这是我的测试: 我写了2节课: 和 我编译了两个类,并在通用类的某个地方看到了这一行 在非泛型类中: 所以很明显我在字节码中有通用信息,那么这个擦除的东西是什么? 问题答案: 一些通用类型信息存储在属性中。请参阅JLS 4.8 和4.6以及JVM规范4.3.4。
我有一个返回泛型的函数: 所以,当我试图匹配一个函数结果时,我的问题是: 我得到一个警告:“类型模式数组[CustomerInfo到[CustomerApplication到]]中的非变量类型参数CustomerApplication-DDTO未选中,因为它已被擦除消除。” 这是否意味着在Array[]中可以得到任何类型的数组?所以我已经阅读了关于ClassTag和TypeTag的文章,但是误解了