5

在这段代码中:

public class MyClass {
    private Object innerValue;
    public Object getInnerValue() {
        return this.innerValue;
    }
    public void setInnerValue(Object innerValue) {
        this.innerValue = innerValue;
    }
}

public class MyClassReadOnly extends MyClass {
    MyClassReadOnly(MyClass cls) {
        // Make a field by field copy
        super.setInnerValue(cls.getInnerValue());
    }
    public void setInnerValue(Object innerValue) {
        throw new UnsupportedOperationException(
                            "This is a read-only instance"
                        );
    }
}

编译器正确地抱怨MyClassReadOnly.setInnerValue()中未使用的参数(从不读取) innerValue

我不想禁用这种警告,因为它通常非常有用,我也不希望有任何警告以具有高信噪比。

我不能将@SuppressWarnings()构造用作另一个建议的问题,因为它仅适用于 Java 1.4。

我想过插入这样的虚拟代码,但不是很令人满意:

public void setInnerValue(Object innerValue) {
    if (innerValue != null) { /* Do Nothing, but keep the compiler happy */ }
    throw new UnsupportedOperationException("This is a read-only instance");
}
4

5 回答 5

11

警告不是问题,恐怕是设计问题。

您当前的层次结构违反了 Liskov 的替换原则,因为接收 MyClass 实例的类期望 setInnerValue 工作,并且可能无法正确处理此异常。你可以说一个可读写的 X 是一种可读的 X,但你不能说一个可读的 X 是一种可读写的 X。

当我遇到这种情况时,我创建了一个名为 IMyX 的带有读取的接口,一个名为 IMutableMyX 的带有写入的子接口,然后实际的类实现了 IMutableMyX,因此也实现了 IMyX。然后我非常小心,只在需要时通过 IMutableMyX,并在所有其他情况下通过 IMyX。

我觉得使用编译器和类型来限制访问比依靠运行时异常更好。它还使您的代码更清晰,并在您确实需要写访问时强制您显式地向下转换接口。

我意识到这并不能回答您关于摆脱警告的问题。但是警告可以被抑制、忽略或解决。未使用的参数通常是一种难闻的气味,表明您的方法可能没有按照预期进行。方法应该只获取必要的参数。如果不使用该参数,则该参数不是必需的,因此需要更改某些内容。

于 2009-04-24T17:10:51.863 回答
0

恐怕你被虚拟代码困住了。在 C/C++ 中,您可以使用宏 ( #define _unused(x) ((void) x)),但(void) variable;在 Java 中不是有效的语句。

如果它让你感觉更好,编译器可能会优化掉空的 if 块。

于 2009-04-24T17:03:50.710 回答
0

您可以安全地输入以下行 innerValue = null:在所有未使用的参数的函数顶部。它不会影响调用者,但会让编译器满意。

于 2009-04-24T17:05:02.407 回答
0

我不会为了让编译器警告消失而玩任何“代码技巧”,希望编译器能够优化这些技巧。事实上,这个编译器警告真的有用吗?我只会禁用它。使用 Java 5 后,您可以使用@SuppressWarnings并重新启用它。

IMO,仅仅因为它们存在就启用所有可能的警告是一个坏主意,然后着手让每一个警告消失。找出哪些警告实际上对您的环境有意义,然后禁用其余警告。

于 2009-04-24T17:09:07.467 回答
0

如果您使用的是 Eclipse (?),您可以打开 Parameter Is Never Read 警告,但忽略覆盖和实现方法(这将解决这个特定问题)的情况,以及单独使用“@param”标签记录的情况(虽然这当然不适用于 Java 1.4)。我希望大多数其他 Java IDE 都可以使用类似的设置。

于 2009-04-24T17:21:23.570 回答