¿Cómo deshabilitar la advertencia en Sonar: Hide Utility Class Constructor?

5 minutos de lectura

Avatar de usuario de Oomph Fortuity
Oomph Fortuity

Recibo esta advertencia en Sonar:

Ocultar constructor de clase de utilidad:

Las clases de utilidad no deben tener un constructor público o predeterminado

Mi clase:

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

Quiero una solución para eliminar esto. advertencia en Sonda Qube.

  • Mejor deshabilite esta inútil advertencia de Sonar. El constructor privado agrega ruido de código solo para mantener feliz alguna regla de Sonar arbitraria. Vea aquí cómo deshabilitar una regla: sqa.stackexchange.com/questions/24734/…

    – juan16384

    17 de febrero de 2020 a las 11:18

Avatar de usuario de RoflcoptrException
RoflcoptrException

Si esta clase es solo una clase de utilidad, debe hacer que la clase sea final y definir un constructor privado:

public final class FilePathHelper {
   private FilePathHelper() {
      //not called
   }
}

Esto evita que el constructor predeterminado sin parámetros se use en otras partes de su código.

Además, puede hacer que la clase sea final, de modo que no se pueda ampliar en subclases, lo cual es una buena práctica para las clases de utilidad. Dado que declaró solo un constructor privado, otras clases no podrían extenderlo de todos modos, pero aún es una buena práctica marcar la clase como final.

  • final es en realidad redundante: una clase con nada más que constructores privados ya es efectivamente definitiva. Sin embargo, no hace daño marcarlo.

    – Marko Topolnik

    18 de enero de 2013 a las 12:23


  • deber marcar la clase como final para que Sonar realmente considere la violación resuelta. Solo agregar un constructor privado no elimina la violación.

    – Cebence

    23 de abril de 2013 a las 11:19


  • ¿Hay alguna regla de Sonar que deba habilitar para esto? He hecho mi clase de utilidad. final y tener un constructor privado. El constructor ahora está marcado como la “línea descubierta”

    – Karthick S.

    11 de agosto de 2014 a las 7:15

  • De hecho, ¿cómo se supone que debe probar/cubrir ese código ‘inalcanzable’?

    – dokaspar

    11/06/2015 a las 20:25

  • Entonces, ¿deberíamos agregar código innecesario a nuestras clases, solo para hacer felices algunas herramientas de análisis? Alguien puede extender o instanciar esta clase. ¿Y qué? ¿Por qué es esto crítico? ¿Puede causar algunos errores? ¿O por qué debería usar herramientas como PowerMock para probar un constructor privado nunca usado, solo para cumplir con los requisitos de Sonar y mi herramienta de cobertura de código?

    – Sergej Werfel

    26 oct 2016 a las 10:49


Avatar de usuario de Jon Skeet
jon skeet

No conozco a Sonar, pero sospecho que está buscando un constructor privado:

private FilePathHelper() {
    // No-op; won't be called
}

De lo contrario, el compilador de Java proporcionará un constructor público sin parámetros, que realmente no desea.

(También debe hacer que la clase sea final, aunque otras clases no podrían extenderla de todos modos debido a que solo tiene un constructor privado).

Avatar de usuario de Peter Lawrey
pedro laurey

Uso una enumeración sin instancias.

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

    public static int myUtilityMethod(int x) {
        return x * x;
    }
}

puedes llamar a esto usando

int y = MyUtils.myUtilityMethod(5); // returns 25.

  • ¿Puede mostrarnos más códigos para esta solución? Acerca del uso enum como una clase de utilidad?

    – Jin Kwon

    26 de febrero de 2016 a las 13:05

  • @JinKwon He agregado un ejemplo. ¿Tienes una duda específica?

    – Peter Lawrey

    26 de febrero de 2016 a las 13:09

  • No, solo quería saber un ejemplo. Gracias. Nunca he pensado en esta forma.

    – Jin Kwon

    26 de febrero de 2016 a las 13:17

  • Usualmente uso Enums para las clases de Utilidad, pero checkstyle 7.0 para JDK8 NO funciona con el ejemplo proporcionado…

    – Marcello de Sales

    12/07/2016 a las 20:51

  • @MarcellodeSales Hace muchos años que no pruebo checkstyle. Prefiero las herramientas que no solo encuentran problemas, sino que también tienen soluciones automáticas para ellos. 😉

    – Peter Lawrey

    13 de julio de 2016 a las 7:45

La mejor práctica es arrojar un error si se construye la clase.

Ejemplo:

/**
 * 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.");
}

Avatar de usuario de Roman Topalov
romano topalov

Puede usar la anotación de Lombok para evitar una inicialización innecesaria.

Usando @NoArgsConstructor con AccessLevel.PRIVATE como abajo:

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FilePathHelper {
   // your code 
}

avatar de usuario de user431640
usuario431640

Recomiendo simplemente deshabilitar esta regla en Sonar, no hay un beneficio real de introducir un constructor privado, solo caracteres redundantes en su base de código que otras personas necesitan leer y la computadora necesita almacenar y procesar.

Avatar de usuario de ℛɑƒæĿᴿᴹᴿ
ℛɑƒaeĿᴿᴹᴿ

uso alternativo Lombok es uso @UtilityClass anotación.

@UtilityClass se introdujo como una característica experimental en Lombok v1.16.2:

Si una clase se anota con @UtilityClassle suceden las siguientes cosas:

  • Está marcado como definitivo.
  • Si se declaran constructores en él, se genera un error.
    • De lo contrario, un constructor privado sin argumentos es generado; lanza un UnsupportedOperationException.
  • Todos los métodosclases internas y campos en la clase están marcados static.

Visión general:

Una clase de utilidad es una clase que es solo un espacio de nombres para funciones. No pueden existir instancias de él, y todos sus miembros son estáticos. Por ejemplo, java.lang.Math y java.util.Collections son clases de utilidad bien conocidas.

Esta anotación convierte automáticamente la clase anotada en una.

No se puede instanciar una clase de utilidad.

Marcando tu clase con @UtilityClass, lombok generará automáticamente un constructor privado que arroja una excepción, marca como error cualquier constructor explícito que agregue y marca la clase como final.

Si la clase es una clase interna, la clase también se marca estático.

Todos los miembros de una clase de utilidad se marcan automáticamente como estáticos. Incluso campos y clases internas.

Ejemplo:

import lombok.experimental.UtilityClass;

@UtilityClass
public class FilePathHelper {

    private static String resourcesPath;

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

Referencia de la documentación oficial:

¿Ha sido útil esta solución?