我们通过将大部分构造函数代码移至 onInitialize()
来避免此 PMD 警告。 。但我们只是将问题(设计缺陷?)转移到另一个地方吗?
即是我们的onInitialize()
只是一个代理构造函数,PMD 没有注意到吗?
当您在构造函数中调用可重写方法时,我们遇到了这种问题,但这似乎源于 Wicket 本身调用一个的事实(无法找到确切的源代码行,但是 onInitialize()
,一个可重写的方法,当您在构造函数中调用 add()
时最终会被调用)。
如果有帮助的话,很高兴提供示例代码。
public class PageA extends WebPage {
protected SomeBean bean;
public PageA() {
add(new Label("foo", "bar"));
bean = new SomeBean();
}
}
public class PageB extends PageA {
public PageB() {
super();
}
@Override
protected void onInitialize() {
add(new Label("rofl", bean.getSomeText()));
}
}
您希望这没问题,但调用onInitialize
不会发生在您可能认为会发生的地方:
调用add()
时在页面上的方法流程是:
MarkupContainer add()
MarkupContainer addedComponent()
Page componentAdded()
MarkupContainer initialize()
Component fireInitialize()
Component onInitialize()
正如您所看到的,如果您将组件添加到WebPage
onInitialize()
方法被触发,这是一个可重写的方法,导致上面看起来正常的代码实例创建 NullPointerException
s。
您收到的关于可能发生这种情况的唯一警告是 onInitialize()
的 JavaDoc :
block 引用>NOTE:The timing of this call is not precise, the contract is that it is called sometime before {@link Component#onBeforeRender()}.
最佳答案
如果您仅从容器的 onInitialized()
方法内部向容器添加组件,则不会出现此问题。但 PMD 无法验证,至少内置规则无法验证。
不过,我不认为这是一个设计缺陷。这是一个设计决策。。您无法将所有设计都基于静态分析工具和预定义规则。 API 可用性也是设计的一个重要方面,有时甚至比设计原则更重要。
例如,CQS (Command-Query Separation)原则要求做某事(更改状态)的方法不应返回任何内容,并且返回某事的方法不应有任何副作用(更改状态)。
如果这是一条硬性规则,则无法实现流畅的接口(interface)(更改对象状态并返回 this
,允许方法链接的方法)。 Wicket 广泛使用它(几乎所有组件操作方法都返回 this
),这也是它使用起来很有趣的原因之一。
PMD 是一个非常有用的工具。但你必须是工具的主人,而不是它的奴隶。您应该将其警告视为可能的问题,但如果您对自己的设计选择充满信心,只需标记要绕过的代码即可。
关于java - Wicket 和 'constructor calls overridable method' PMD 警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6291657/