标准的Spring Boot应用程序有一些主要的方法类文件,比如SampleApplication.java
,它看起来像这样:
@SpringBootApplication
@RestController
public class SampleApplication {
public static void main(final String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
但PMD静态分析将其标记为错误(HideUtilityClassConstructorCheck):
实用程序类不应具有公共或默认构造函数。
确保实用程序类(在其API中仅包含静态方法或字段的类)没有公共构造函数。
基本原理:实例化实用程序类没有意义。因此构造函数应该是私有的或(如果您想允许子类化)受保护。一个常见的错误是忘记隐藏默认构造函数。
如果您对构造函数进行了保护,您可能需要考虑以下构造函数实现技术来禁止实例化子类:
public class StringUtils // not final to allow subclassing {protected StringUtils(){//阻止来自子类的调用抛出new UnsupportedOperationException(); public static int count(char c,String s){// ...}}
为什么是这样?我应该抑制这个PMD错误吗?
检查说明了一切。
默认情况下,任何代码检查器(IntelliJ IDEA,FindBugs,PMD,Sonar)都假设如果类只有static
方法,则它是utility class。实用程序类的示例是java.lang.Math
,如下所示:
public final class Math {
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
public static double exp(double a) {
...
}
// More helper methods
}
这样的类被设计为使用它作为一个静态函数包:为它声明私有构造函数是一个好习惯,所以没有人会错误地实例化它并声明类final
,因为扩展它是没有意义的。
在您的情况下(以及几乎每个Spring Boot应用程序的入口点)SampleApplication
类都有一个public static void main
方法,因此PMD决定其实用程序类,检查私有构造和最终修饰符并标记错误。这不是问题,PMD只是不了解Spring Boot或任何其他框架及其入口点,因此完全有理由抑制此警告并将您的类从PMD中排除:对我来说,它在语义上比添加私有构造函数更正确应用入口点。
使用PMD规则集XML文件中的以下片段,可以仅针对具有@SpringBootApplication
批注的类抑制PMD UseUtilityClass规则:
<rule ref="category/java/design.xml/UseUtilityClass">
<properties>
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration/preceding-sibling::Annotation/MarkerAnnotation/Name[@Image='SpringBootApplication']" />
</properties>
</rule>