2013-01-18 6 views
1

Je classe « constructeur » et Sonar donne l'avertissement suivant:Java - manquant Méthode statique non instanciable Classe

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 

Comment aurais-je factoriser cette classe pour satisfaire le chèque ci-dessus? Je me gratte la tête parce que j'utilise cette classe.

utilisation Exemple:

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(); 

classe elle-même:

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

Répondre

1

Étant donné que votre classe imbriquée Builder est public et static, je vois vraiment peu d'avantages en étant imbriquée du tout. Je recommanderais de le sortir dans sa propre classe de premier niveau. Bien sûr, ce n'est pas pourquoi PMD se plaint. Votre classe externe, ViewBuilder, n'a aucun constructeur public et aucune méthode statique. Comme il existe actuellement, c'est un «wrapper d'espace de noms» assez inutile autour de votre classe Builder. Ajoutez-y un constructeur ou éliminez-le complètement.

+0

+1. "public et statique, je vois vraiment peu d'avantages à ce qu'il soit imbriqué du tout" – kosa

+3

C'est exactement comme cela que vous implémentez un "pattern builder". Si vous pensez qu'il y a "peu de valeur", je vous recommande de faire quelques recherches sur le point du modèle de constructeur. Bref, c'est pour pouvoir créer de façon fiable un objet dans un état garanti. La classe privée est utilisée pour s'assurer que le constructeur des classes externes est UNIQUEMENT appelé après l'appel de la fonction build() et fournit également un hookpoint pour valider les variables passées. Maintenant, vous pouvez faire une vérification de la santé mentale si vous avez le " "valeurs requises" passées ou non. Voir la réponse de bmg pour plus d'informations. – Russ

2

La règle PMD SonarQube doit être mise à jour pour prendre en compte l'accesseur dans la classe de générateur statique imbriquée.

Il y a un problème PMD créé pour cela, mais il semble abandonné: http://sourceforge.net/p/pmd/bugs/955/

Je suis en désaccord avec « refactoring » pour se débarrasser de cette violation sonar, le modèle de constructeur est bien connu et très utile lors de la création d'objets complexes . Voir «Effective Java», chapitre 2, élément 2. http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2

+0

Dieu merci, quelqu'un a parlé de la valeur du modèle de constructeur. Le problème n'est * pas * le code de cette personne. C'est que le sonar n'est pas assez "intelligent" pour comprendre que le constructeur privé IS est appelé par une fonction interne "build()" et que Sonar devrait alors se rendre compte que la fonctionnalité est publique et cesser de se plaindre. + des points brownie pour faire référence au livre de Josh Bloch. Quiconque pense que ce code ne fournit aucune valeur telle qu'elle est écrite doit à lui-même choisir Java efficace et lui donner une lecture. – Russ

Questions connexes