Práctica recomendada de Java: clase con solo métodos estáticos

7 minutos de lectura

avatar de usuario de user3629892
usuario3629892

Tengo una aplicación donde tengo una clase llamada PlausibilityChecker. Esta clase solo tiene métodos estáticos, como checkZipcodeFormat o checkMailFormat. Los uso en mis clases de GUI para verificar la entrada antes de enviarla a la capa inferior.

¿Es esta una buena práctica? Pensé que usaría solo métodos estáticos para no tener que preocuparme por pasar una instancia a las clases de GUI o tener un campo de instancia en cada clase de interfaz gráfica de usuario que no haga referencia a un objeto de interfaz gráfica de usuario.

Me di cuenta de que el Files clase de Java NIO solo tiene métodos estáticos, así que asumo que esto no puede ser tan terriblemente incorrecto.

  • Mientras no tenga estado, está bien.

    – Sotirios Delimanolis

    14 de julio de 2015 a las 14:48

  • Las clases estáticas están bien, pero no olvide agregar un constructor privado. Ah, y tenga en cuenta los accesos de subprocesos múltiples.

    – m0skit0

    14 de julio de 2015 a las 14:49


  • Proporcione más información sobre la estructura de su programa.

    – Marún

    14/07/2015 a las 14:50

  • Por lo general, nombramos clases como *Helper, no hay nada de malo en tenerlas. Extra private constuctor() puede evitar la instanciación,

    – ángel de la muerte908

    14 de julio de 2015 a las 14:51

  • También lo he visto a menudo llamado “Utilidad”

    – Doble doble

    14 de julio de 2015 a las 14:51


Avatar de usuario de Luiggi Mendoza
Luis Mendoza

Yo diría que lo estás haciendo bien. Aparte de eso, algunos consejos para su clase de utilidad:

  • Asegúrate de que no tenga ningún estado. Esto es, no hay ningún campo en la clase a menos que se declare static final. Además, asegúrese de que este campo también sea inmutable, por ejemplo Strings.
  • Asegúrese de que no pueda ser una superclase de otras clases. hacer la clase final por lo que otros programadores no pueden extenderlo.
  • Este es discutible, pero puede declarar un constructor sin argumentos private, por lo que ninguna otra clase podría crear una instancia de su clase de utilidad (usar la reflexión o algo similar servirá, pero no hay necesidad de protegerse con la clase). ¿Por qué no puedes hacer esto? Bueno, este es el caso extraño en el que desea/necesita inyectar una instancia de la clase de utilidad, por ejemplo, a través de una interfaz en lugar de usarla directamente a lo largo de su clase. Aquí hay un ejemplo de esto. Este diseño es realmente extraño pero puede suceder (como se muestra en el enlace de arriba), pero si no lo ejecuta en tal caso, el mejor consejo es mantener el constructor private.

Hay muchas bibliotecas que proporcionan clases de utilidad para ayudarnos a los programadores con nuestro trabajo. Uno de los más conocidos es apache común conjunto de bibliotecas. Es de código abierto y puede consultar el código para ver cómo diseñan estas clases de utilidad para crear la suya. (DESCARGO DE RESPONSABILIDAD: no trabajo ni apoyo estas bibliotecas, soy un usuario feliz de ellas)

Nota IMPORTANTE: Evite usar un singleton para su clase de utilidad.

  • ¿No sería mejor si usa un patrón singleton y crea todas las funciones normalmente excepto por getInstance() ?

    – Los errores suceden

    14 de julio de 2015 a las 14:53

  • @BugsHappen no use singleton, es malvado.

    –Luiggi Mendoza

    14/07/2015 a las 14:55

  • para el primer punto, creo que no es suficiente decir que asegúrese de que todos los campos sean estáticos finales, ya que un campo final puede hacer referencia a algo mutable; Yo diría que se asegure de que no haya nada mutable y que no haya dependencias de nada externo (sistema de archivos, base de datos, etc.). aunque el ejemplo de nio Files va en contra de esa última parte.

    – Nathan Hughes

    14 de julio de 2015 a las 15:02


En Java 8 ahora puede cambiar sus clases de utilidad estáticas a interfaces con implementaciones estáticas. Esto elimina la necesidad de hacer que la clase sea final y tener que proporcionar un constructor privado. Es tan simple como cambiar ‘clase’ por ‘interfaz’ y eliminar la palabra final si la tiene (todas las interfaces son abstractas, por lo que no pueden ser definitivas). Dado que los métodos de interfaz siempre son públicos, puede eliminar cualquier ámbito público de ellos. Si tiene un constructor privado, elimínelo también (no puede compilar una interfaz con un constructor ya que no se pueden instanciar). Es menos código y se ve más limpio. No tendrá que refactorizar ninguna clase que ya lo use.

  • Los métodos de extensión no se admiten en el nivel de idioma ‘7’. El método de interfaz estática requiere el nivel de API 24

    – Vahag Chajoyan

    2 de julio de 2019 a las 9:27


Avatar de usuario de ZhongYu
ZhongYu

No se preocupe por la subclasificación o la creación de instancias. Las siguientes clases de utilidad en JDK se pueden subclasificar o crear instancias, pero nadie las ha usado indebidamente en todos esos años. la gente no es que tonto.

java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder                                   ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML

Sin embargo, como API pública, desea suprimir el constructor predeterminado; de lo contrario, hay un constructor no documentado en la página de javadoc que es incómodo y confuso. Para sus propias API internas, no importa, a nadie le importa.

Sin embargo, no hay razón para suprimir la subclasificación. Si alguien quiere subclasificar una clase de utilidad, por la razón que sea, que lo haga. Por supuesto, el constructor privado suprimirá la subclasificación como efecto secundario.


En java8, hay más posibilidades de diseño a considerar:

Una interfaz con todos los métodos estáticos. – esto es tan bueno como una clase con todos los métodos estáticos. Ni la interfaz ni la clase están diseñadas para este propósito, por lo que cualquiera de las dos está bien. Sin embargo, no espere heredar estos métodos estáticos en subtipos de la interfaz: los métodos estáticos de la interfaz no son heredables. Un punto a favor para usar la interfaz es que no necesitamos suprimir el constructor predeterminado para que no aparezca en javadoc.

Una interfaz con todos los métodos predeterminados – se accede a través de la herencia. Esto es interesante pero problemático en general (la herencia funciona solo en un contexto no estático). Pero podría ser una mejor opción en algunos diseños de API, por ejemplo, este constructor html API.

  • Esto va en contra del consejo de Joshua Bloch en su libro Java Efectivo, donde le recomienda usar solo interfaces para definir tipos.

    – Ogen

    2 de octubre de 2019 a las 2:10

¿Por qué no debería ser una buena práctica si solo tiene métodos que proporcionan “herramientas” a otras clases? Está bien.

Singleton están bien, dependiendo del contexto.

Con fines de prueba, es posible que desee simular referencias a singletons para evitar efectos secundarios durante las pruebas unitarias. En ese caso, probablemente tenga sentido usar un marco de inyección de dependencia como Spring para manejar la creación de la instancia y usar métodos regulares que pueden anularse en lugar de métodos estáticos.

Si aún planea usar métodos estáticos, asegúrese de que las llamadas sean seguras para subprocesos si se usan en un contexto de subprocesos múltiples. (p. ej., bloqueo doblemente controlado).

  • Métodos estáticos != singleton. Para las clases de utilidad con solo métodos estáticos, a menudo no hay ninguna instancia de la clase.

    – Markusk

    14/07/2015 a las 15:00

Las clases con solo métodos estáticos son un patrón común en Java para los métodos de utilidad. Los ejemplos en la biblioteca estándar incluyen archivos, Coleccionesy Ejecutores.

Para tales clases de utilidad, es una buena idea asegurarse de que su clase no pueda ser instanciada, para dejar clara la intención de la clase. Puede hacerlo declarando explícitamente un constructor privado. Ver Ítem ​​4: Hacer cumplir la no instanciabilidad con un constructor privado en “Effective Java” de Josh Bloch para más detalles.

  • Métodos estáticos != singleton. Para las clases de utilidad con solo métodos estáticos, a menudo no hay ninguna instancia de la clase.

    – Markusk

    14/07/2015 a las 15:00

¿Ha sido útil esta solución?