标记为@NotNull的最终字段未初始化

时间:2017-03-10 13:13:16

标签: java selenium-webdriver

我有这段代码:

public static class MyWebDriver extends RemoteWebDriver {
    @NotNull
    private final String nodeId;

    public MyRemoteWebDriver(@NotNull String nodeId) {
        super();
        this.nodeId = nodeId;
    }

    @Override
    public void quit() {
        System.out.println("deleting node: " + nodeId);
    }
}

并且保证传递给构造函数的nodeId不是null。由于nodeId字段为final,我希望它在我的quit()方法中初始化。

但是,在super()构造函数中有一个try-catch块,如果出现异常调用 quit() 方法,则抛出异常。在这种情况下,我在nodeId方法中获得的quit()未初始化(具有null值)。

除了

之外,有没有办法避免它
@Override
public void quit() {
    if (nodeId != null) {
        System.out.println("deleting node: " + nodeId);
    }
}
这个?这看起来很愚蠢,因为nodeId被标记为@NotNull

4 个答案:

答案 0 :(得分:4)

  

但是,在super()构造函数中有一个try-catch块,在异常调用的情况下调用quit()

这是两个问题:

    除了在(final)成员变量中存储给定参数外,
  1. 构造函数不应该做任何工作。

    [编辑]

      

    这是否意味着类不应验证其输入?我知道很多人不同意他们的所有物品都可能无效,而不是根本不存在。 - 克里斯

    &#34;不应该做任何工作&#34; 我的意思是构造函数不应该从参数中计算任何属性值,也不应该调用依赖项或非公共方法来进行检查。< / p>

  2. 构造函数不应该直接或间接地调用除private和/或final方法(在类中)之外的任何其他方法(即,你不得&#39) ; t调用final方法,然后调用非final方法。

  3. 您遇到此问题的原因是违反单一责任模式关注点分离

    你在超类构造函数中做的事情应该很可能是在一个单独的类中完成的,只有那个进程的结果应该传递给你的类(及其超类)。

    这显然意味着quit()方法也属于另一个类。

答案 1 :(得分:2)

这当然可以通过Java的工作原理轻松解释。类型为MyWebDriver的对象未初始化,包括其字段,即包括在您的情况nodeId中,直到其从超类继承的字段被初始化,即在您的情况下,直到super()回报。

因此,如果super中出现异常,则nodeId null"#c" + userInput.value。{/ p>

除非您使用的框架(您未指定)提供了一些解决方法,否则我认为没有任何解决方案(除了一些类似于您建议的内容)。

答案 2 :(得分:1)

您可以将初始化逻辑从超级构造函数移动到受保护的init()方法,并在nodeId初始化后调用它。

也许可以在这里使用更清晰的设计,但如果没有完整的例子,很难提出任何建议。

答案 3 :(得分:0)

您应该在RemoteWebDriver后面更改bean,添加quit这个布尔比较。或者甚至更好,你不应该在构造函数上调用任何方法,只构造实例本身的设置值。之后,计算新实例变量boolean isItFullyConstructed的值,如果为false,则调用导致问题的原始try / catch逻辑。这可行吗?