1

我有“builder”类,Sonar 给出以下警告:

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; }
}
4

3 回答 3

4

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

为此创建了一个 PMD 问题,但它看起来已被废弃:http: //sourceforge.net/p/pmd/bugs/955/

我不同意“重构”以摆脱这种声纳违规,构建器模式是众所周知的并且在创建复杂对象时非常有用。参见“Effective Java”第 2 章第 2 项。 http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2

于 2015-03-25T17:32:06.253 回答
1

满足此检查的另一种方法是使构造函数包私有而不是私有。这样做的另一个好处是,编译器将不再需要为内部类生成具有包私有访问权限的附加合成构造函数,请参阅关于内部类中私有方法的问题的答案

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

// private constructor to enforce the use of Builder.build()
@SuppressWarnings("pmd:MissingStaticMethodInNonInstantiatableClass")
于 2018-04-04T15:38:44.533 回答
0

鉴于您的嵌套 Builder 类是publicand static,我真的认为嵌套它没有什么好处。我建议将其分解为自己的顶级课程。当然,这不是 PMD 抱怨的原因。您的外部类ViewBuilder没有公共构造函数,也没有静态方法。Builder正如它现在存在的那样,它是围绕你的类的一个相当无用的“命名空间包装器” 。要么向它添加一个构造函数,要么完全摆脱它。

于 2013-01-18T22:55:45.087 回答