Java-不可实例化类中缺少静态方法

Java-不可实例化类中缺少静态方法,java,sonarqube,Java,Sonarqube,我有“建筑工人”等级,声纳发出以下警告: Missing Static Method In Non Instantiatable Class pmd : MissingStaticMethodInNonInstantiatableClass A class that has private constructors and does not have any static methods or fields cannot be used 如何重构该类以满足上述检查? 我挠头是因为我用过那门课

我有“建筑工人”等级,声纳发出以下警告:

Missing Static Method In Non Instantiatable Class
pmd : MissingStaticMethodInNonInstantiatableClass
A class that has private constructors and does not have any static methods or fields cannot be used
如何重构该类以满足上述检查? 我挠头是因为我用过那门课

样本使用:

ViewBuilder vb = new ViewBuilder.Builder()
    .modelPart(CONTENT_PAGE, contentPageDao.get(id))
    .modelPart("navigation_sections", navigationSectionDao.list() )
    .modelPart("available_tags", tagDao.list() )
    .modelPart("available_albums", albumDao.list() )
    .section(CONTENT_PAGE)
    .page("index")
    .element("form")
    .action("/admin/content_page/save/" + id + ".html")
    .build();
类本身:

import java.util.HashMap;
import java.util.Map;


 public final class ViewBuilder {

    private static final String ADMIN_LAYOUT = "admin/layout";
    private String layout = ADMIN_LAYOUT;
    private String section = "";

  private static Map<String, Object> viewParts = new HashMap<String, Object>();

  /**
   * @return the layout
   */ public String getLayout() {
    return layout;
  }

  /**
   * @param layout the layout to set
   */ public void setLayout(String layout) {
    this.layout = layout;
  }

  /**
   * @return the section
   */ public String getSection() {
    return section;
  }

  /**
   * @param section the section to set
   */ public void setSection(String section) {
    this.section = section;
  }

  public static class Builder{

    // required params
    private String layout;
    private String section;

    // optional params
    private Map<String, Object > viewParts = new HashMap<String, Object >();

    public Builder(){

        this.layout = ADMIN_LAYOUT;
        viewParts.put("layout", ADMIN_LAYOUT);

    }
    public Builder( String layout ){

      if( layout != null ){
        this.layout = layout;
        viewParts.put("layout", layout );
      } else {
        this.layout = ADMIN_LAYOUT;
        viewParts.put("layout", ADMIN_LAYOUT);
      }

    }// constructor
    public Builder modelPart( String val, Object o ){
      this.viewParts.put(val, o );
      return this;
    }

    public Builder action( String val ){
      this.viewParts.put("action", val);
      return this;
    }
    public Builder element( String val ){
      this.viewParts.put("element", val);
      return this;
    }
    public Builder section( String val ){
      this.section = val;
      this.viewParts.put("section", val);
      return this;
    }
    public Builder page( String val ){
      this.viewParts.put("page", val);
      return this;
    }
    public Builder layout( String val ){
      this.layout = val;
      return this;
    }

    public ViewBuilder build( ){
      return new ViewBuilder( this );
    }


  }// Builder

    private ViewBuilder(Builder builder){
      this.section = builder.section;
      this.layout = builder.layout;

      viewParts = builder.viewParts;
    }

  /**
   * Get the value of viewParts
   *
   * @return the value of viewParts
   */
  public Map<String, Object> getViewParts() { return viewParts; }

  /**
   * Set the value of viewParts
   *
   * @param viewParts new value of viewParts
   */
  public void setViewParts(Map<String, Object> viewParts) { this.viewParts = viewParts; }
}
import java.util.HashMap;
导入java.util.Map;
公共最终类ViewBuilder{
私有静态最终字符串ADMIN\u LAYOUT=“ADMIN/LAYOUT”;
私有字符串布局=管理布局;
私有字符串部分=”;
private static Map viewParts=new HashMap();
/**
*@返回布局
*/公共字符串getLayout(){
返回布局;
}
/**
*@param layout要设置的布局
*/公共void setLayout(字符串布局){
this.layout=布局;
}
/**
*@返回该节
*/公共字符串getSection(){
返回段;
}
/**
*@param section要设置的节
*/公共无效设置部分(字符串部分){
this.section=section;
}
公共静态类生成器{
//必需参数
私有字符串布局;
私有字符串部分;
//可选参数
private-Map-viewParts=new-HashMap();
公共建筑商(){
this.layout=管理布局;
viewParts.put(“布局”,管理布局);
}
公共生成器(字符串布局){
if(布局!=null){
this.layout=布局;
viewParts.put(“布局”,布局);
}否则{
this.layout=管理布局;
viewParts.put(“布局”,管理布局);
}
}//建造师
公共生成器modelPart(字符串val,对象o){
this.viewParts.put(val,o);
归还这个;
}
公共生成器操作(字符串val){
this.viewParts.put(“action”,val);
归还这个;
}
公共生成器元素(字符串val){
this.viewParts.put(“元素”,val);
归还这个;
}
公共生成器部分(字符串val){
this.section=val;
this.viewParts.put(“section”,val);
归还这个;
}
公共生成器页面(字符串val){
this.viewParts.put(“page”,val);
归还这个;
}
公共生成器布局(字符串val){
this.layout=val;
归还这个;
}
公共ViewBuilder生成(){
返回新的ViewBuilder(此);
}
}//建筑商
专用视图生成器(生成器){
this.section=builder.section;
this.layout=builder.layout;
viewParts=builder.viewParts;
}
/**
*获取viewParts的值
*
*@返回viewParts的值
*/
公共映射getViewParts(){return viewParts;}
/**
*设置viewParts的值
*
*@param viewParts viewParts的新值
*/
public void setViewParts(映射viewParts){this.viewParts=viewParts;}
}

鉴于您的嵌套构建器类是
公共的
静态的
,我真的看不到嵌套的好处。我建议将其划分为自己的顶级课程。当然,这不是PMD抱怨的原因。您的外部类,
ViewBuilder
,没有公共构造函数,也没有静态方法。因为它现在已经存在,所以它在
Builder
类周围是一个相当无用的“名称空间包装器”。要么给它添加一个构造函数,要么完全去掉它。

鉴于您的嵌套构建器类是
public
static
,我真的认为嵌套它没有什么好处。我建议将其划分为自己的顶级课程。当然,这不是PMD抱怨的原因。您的外部类,
ViewBuilder
,没有公共构造函数,也没有静态方法。因为它现在已经存在,所以它在
Builder
类周围是一个相当无用的“名称空间包装器”。要么向其添加构造函数,要么完全删除它。

需要更新SonarQube PMD规则,以考虑静态嵌套构建器类中的访问器

为此创建了PMD问题,但看起来已被放弃:

我不同意“重构”来消除这种声纳冲突,构建器模式是众所周知的,在创建复杂对象时非常有用。 参见“有效Java”第2章第2项。

需要更新SonarQube PMD规则,以考虑静态嵌套生成器类中的访问器

为此创建了PMD问题,但看起来已被放弃:

我不同意“重构”来消除这种声纳冲突,构建器模式是众所周知的,在创建复杂对象时非常有用。 参见“有效Java”第2章第2项。
满足此检查的另一种方法是使构造函数包私有而不是私有。这样做的另一个好处是,编译器不再需要为内部类ref生成具有包私有访问权限的额外合成构造函数

如果您强烈希望保持构造函数的私有性,以防止同一包中的其他类在不使用
Builder.build()
的情况下创建实例,那么您应该能够通过以下方法抑制Sonar问题:

// private constructor to enforce the use of Builder.build()
@SuppressWarnings("pmd:MissingStaticMethodInNonInstantiatableClass")

满足此检查的另一种方法是使构造函数包私有而不是私有。这样做的另一个好处是,编译器不再需要为内部类ref生成具有包私有访问权限的额外合成构造函数

如果您强烈希望保持构造函数的私有性,以防止同一包中的其他类在不使用
Builder.build()
的情况下创建实例,那么您应该能够通过以下方法抑制Sonar问题:

// private constructor to enforce the use of Builder.build()
@SuppressWarnings("pmd:MissingStaticMethodInNonInstantiatableClass")

+1.“公共的和静态的,我真的看不到嵌套的好处”这正是实现“构建器模式”的方式。如果您认为它“没有什么价值”,我建议您对构建器模式进行一些研究。简而言之,就是能够在保证状态下可靠地创建对象。私有类用于确保外部类构造函数是唯一的调用