我有几个未经检查的警告,我想抑制但在运行中我仍然看到这条消息:
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
我使用以下类型的注释,实际上警告消息在IDE源代码中消失。
@Override @SuppressWarnings("unchecked")
public GroundBase<J> getGround() {
return ground;
}
我将我的代码作为公共API分发,我想知道用户在使用过程中是否会看到该消息。
我正在使用 junit 测试我的代码。 我使用的是Java 8和intelliJ 2016.3.6。
我查看了-Xlint:unchecked
建议详细信息。代码中没有更多未注释的部分,但编译器建议仍然不会消失(或减少)。
修改
更好地将我得到的警告之一进行了语境化,这里是一个简化但仍然相关的代码部分:
abstract public class MORBase<J extends OWLObject>
implements Descriptor<OWLReferences,J>, MORGround<J>
@Override @SuppressWarnings("unchecked")
public GroundBase<J> getGround() {
return ground;
}
}
interface Ground<O,J>{
Ground<J> getGround();
}
interface Descriptor<O,J> {
<I extends Ground<O,J>> I getGround();
}
这里有关于它的完整信息:
warning: [unchecked] getGround() in MORBase implements <I>getGround() in Descriptor
public GroundBase<J> getGround() {
^
return type requires unchecked conversion from GroundBase<J#1> to I
where J#1,I,O,J#2 are type-variables:
J#1 extends OWLObject declared in class MORBase
I extends Ground<O,J#2> declared in method <I>getGround()
O extends Object declared in interface Descriptor
J#2 extends Object declared in interface Descriptor
我很欣赏有关界面设计的建议,但我的问题与警告未被抑制的原因有关。
答案 0 :(得分:1)
您的问题实际上取决于getGround()
中Descriptor
的定义。类型变量I
在getGround()
的声明中是免费的,这意味着您的方法承诺返回 调用者选择的任何类型!返回类型I
的唯一方法是以某种方式破坏类型系统(例如,通过抛出异常或返回null
)。
编译器正确检测到I
中来电者使用getGround()
的{{1}}可能与J
的实施中的getGround()
不同在MORBase
中,但编译器无法发出任何字节码来检查类型(因为您正在编译MORBase
,但字节码需要插入调用者 getGround()
)。由于它无法检查类型,并且无法插入代码来检查类型,因此它会正确地发出未经检查的警告。
可以通过将@SuppressWarnings
注释附加到getGround()
界面中的Descriptor
声明来实际抑制此警告,但实际上您不应该这样做。相反,修复你的代码。
我建议的解决方法是简单地在I
的声明中删除类型变量getGround()
,并依靠子类型多态来允许您简单地将getGround()
声明为返回{{1 }}:
Ground<O, J>
如果这不可能,并且您需要能够以interface Descriptor<O,J> {
Ground<O,J> getGround();
}
的子类型返回Ground
的子类型,则需要向Descriptor
添加类型参数以确保类型正确传播到调用者:
Descriptor
请注意,即使指定interface Descriptor<O, J, G extends Ground<O, J>> {
G getGround();
}
接口上的getGround()
方法只返回Descriptor
,Ground<O, J>
的子类型仍然可以将方法专门化为返回更具体的子类型。例如,这是完全合法的(并且是安全的):
Descriptor
如果您想强制执行interface Descriptor<O, J> {
Ground<O, J> getGround();
}
public final class FooDescriptor<O, J> implements Descriptor<O, J> {
@Override
public FooGround<O, J> getGround() {
...
}
}
和FooDescriptor
之间的某种关系,则只会出现此问题。这需要一个Java没有的 traits 系统,或者Java类型系统不支持的更高级的类型约束。因此,如果您确实需要FooGround
和FooDescriptor
之间的关系,则需要添加另一个类型参数来关联它们。但是如果你不严格需要它们之间的关系,不要通过尝试对其进行编码来使你的类型复杂化。
请注意,此问题通常称为“并行继承层次结构”问题,并且在SoftwareEngineering.SE上存在大量关于它的问题,如this one。