隐藏实用程序类构造函数:实用程序类不应具有公共或默认构造函数

Oom*_*ity 85 java constructor sonarqube

我在Sonar上收到了这个警告.我想要解决方法在声纳上删除此警告.我的班级是这样的:

public class FilePathHelper {
    private static String resourcesPath;

    public static String getFilePath(HttpServletRequest request) {
        if(resourcesPath == null) {
            String serverpath=request.getSession().getServletContext().getRealPath("");             
            resourcesPath = serverpath + "/WEB-INF/classes/";   
        }
        return resourcesPath;       
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要适当的解决方案来消除声纳上的这个警告.

Rof*_*ion 160

如果这个类只是一个实用程序类,你应该使类最终并定义一个私有构造函数:

public final class FilePathHelper {

   private FilePathHelper() {
      //not called
   }
}
Run Code Online (Sandbox Code Playgroud)

这可以防止在代码中的其他位置使用默认的无参数构造函数.此外,您可以使类最终,以便它不能在子类中扩展,这是实用程序类的最佳实践.由于您只声明了一个私有构造函数,因此其他类无论如何都无法扩展它,但将该类标记为final是最佳实践.

  • 您必须**将该类标记为Sonar的"final",以实际考虑违规已解决.只是添加私有构造函数不会清除违规. (17认同)
  • `final`实际上是多余的:一个只有私有构造函数的类已经有效了.但是,通过标记它不会造成伤害. (10认同)
  • 那么我们应该为我们的类添加不必要的代码,只是为了让一些分析工具满意吗?有人可以扩展或实例化这个类.所以呢?为什么这很重要?会导致一些错误吗?或者为什么我甚至应该使用像PowerMock这样的工具来测试一个从未使用过的私有构造函数,只是为了满足Sonar和我的代码覆盖工具的要求? (7认同)
  • 实际上,你应该如何测试/覆盖这种"无法访问"的代码? (5认同)
  • 我需要为此启用一些声纳规则吗?我已经使我的实用程序类`final`并拥有一个私有构造函数.构造函数现在标记为"未覆盖的行" (4认同)
  • 因为您要确保该类不是子类. (2认同)
  • @SergejWerfel旧帖子,但我同意。我想知道到底有什么令人信服的理由使它成为最终的或添加私有构造函数。如果有人想实例化我的实用程序类,请继续。我不在乎 除了有人这样说之外,我认为没有任何理由可以认为这是“最佳实践”。如果有人真的可以给出为什么这是最佳实践的正当理由,那么我愿意改变主意。 (2认同)

Jon*_*eet 18

我不知道Sonar,但我怀疑它正在寻找私有构造函数:

private FilePathHelper() {
    // No-op; won't be called
}
Run Code Online (Sandbox Code Playgroud)

否则,Java编译器将提供一个您真正不需要的公共无参数构造函数.

(你也应该把它作为最终的,尽管其他类无论如何都无法扩展它,因为它只有一个私有的构造函数.)


Pet*_*rey 11

我使用没有实例的枚举

public enum MyUtils { 
    ; // no instances
    // class is final and the constructor is private

    public static int myUtilityMethod(int x) {
        return x * x;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以用这个来打电话

int y = MyUtils.myUtilityMethod(5); // returns 25.
Run Code Online (Sandbox Code Playgroud)


jav*_*e42 9

最佳做法是在构造类时抛出错误.

例:

/**
 * The Class FooUtilityService.
 */
final class FooUtilityService{

/**
* Instantiates a new FooUtilityService. Private to prevent instantiation
*/
private FooUtilityService() {

    // Throw an exception if this ever *is* called
    throw new AssertionError("Instantiating utility class.");
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么这是最佳实践?我们在这里得到什么?各个级别都存在愚蠢的情况,但是添加这些行只是为了防止实例化(在这些情况下相当无害)似乎有点过大,考虑到这会引入一个干净的类(其中仅包含常量)的六行代码噪音。 (3认同)
  • @ThomasCarlisle 语言创建者没有创建那些代码分析器;无用的警告是你可以关闭的(比如在项目中的任何地方不使用序列化时臭名昭著的丢失serialVersionId警告)——相反,当有人实例化此类只是为了访问常量时,该工具应该在使用站点发出警告;人们抱怨 Java 过于冗长,并且满足由代码分析器中调整不当的“默认”配置文件强加给我们的任意未经证实的规则也无济于事。 (3认同)

小智 9

您可以只使用 Lombok 注释来避免不必要的初始化。

@NoArgsConstructorAccessLevel.PRIVATE如下一起使用:

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FilePathHelper {
   // your code 
}
Run Code Online (Sandbox Code Playgroud)