【发布时间】:2016-01-06 22:41:15
【问题描述】:
免责声明:这不是关于这个案例(虽然错误听起来一样):class inherits unrelated defaults for spliterator() from types java.util.Set and java.util.List
原因如下:
考虑两个接口(在包“a”中)
interface I1 {
default void x() {}
}
interface I2 {
default void x() {}
}
我很清楚为什么我们不能声明这样的类:
abstract class Bad12 implements I1, I2 {
}
(!) 但是我无法理解参考类型变量的这个限制:
class A<T extends I1&I2> {
List<T> makeList() {
return new ArrayList<>();
}
}
出现错误:class java.lang.Object&a.I1&a.I2 inherits unrelated defaults for x() from types a.I1 and a.I2。
为什么我不能定义这样的类型变量?为什么java 在这种情况下关心不相关的默认值?什么样的类型变量可以“破坏”?
更新:只是为了澄清。我可以创建多个表单类:
class A1 implements I1, I2 {
public void x() { };
}
class A2 implements I1, I2 {
public void x() { };
}
甚至
abstract class A0 implements I1, I2 {
@Override
public abstract void x();
}
等等。为什么我不能为这样的类组声明特殊类型的变量?
UPD-2: 顺便说一句,我在 JLS 中没有发现针对这种情况的任何明显限制。最好通过引用 JLS 来确认您的答案。
UPD-3: 一些用户说这段代码在 Eclipse 中编译得很好。我无法检查它,但我检查了javac 并得到了这个错误:
error: class INT#1 inherits unrelated defaults for x() from types I1 and I2
class A<T extends I1&I2> {
^
where INT#1 is an intersection type:
INT#1 extends Object,I1,I2
1 error
【问题讨论】:
-
如果这被认为是一个错误,我会吃掉我收集的节日帽子。
-
@pvg 请发布吃帽子的视频!类型约束
完全有效;它的意思是“A 只能用 I1 和 I2 的子类型来实例化。编译器无法证明不存在这样的类型,因为实际上可以构造这样的类型。 -
@pvg 边界
只是一个声明,仅使用 Y 和 Z 的子类型来实例化 A 是合法的。如果 Y&Z 不是,编译器将阻止一个合法的类型(例如,Y 和 Z 都是类),并且如果它可以证明不存在这样的类型,则有权拒绝(例如,Y 是不实现 Z 的最终类)。但边界 I1&I2 是有效的。默认方法不应该参与这个计算——那只是一个错误。 -
@Andremoniy 原来是这个现有错误的副本:bugs.openjdk.java.net/browse/JDK-7120669
-
无论如何,我们正在等待来自@pvg 的吃帽子的视频:-)
标签: java java-8 type-variables