2012-03-02 17 views
7

No he utilizado muchos métodos estáticos anteriormente, pero recientemente tiendo a usar más de ellos. Por ejemplo, si quiero establecer un indicador booleano en una clase, o acceder a uno sin la necesidad de pasar el objeto real a través de las clases.Pros y contras de los métodos estáticos de Java

Por ejemplo:

public class MainLoop 
{ 
    private static volatile boolean finished = false; 

    public void run() 
    { 
     while (!finished) 
     { 
      // Do stuff 
     } 

    } 
    // Can be used to shut the application down from other classes, without having the actual object 
    public static void endApplication() 
    { 
     MainLoop.finished = true; 
    } 

} 

¿Es esto algo que debe evitar? ¿Es mejor pasar un objeto para poder usar los métodos de los objetos? ¿El booleano finished cuenta ahora como global, o es igual de seguro?

+0

La variable 'finished' es de hecho" global "para la clase. Java no tiene verdaderas variables "globales" (para todo). –

+1

@Hasslarn: su código está roto (y estoy un poco sorprendido de que después de cuatro respuestas nadie lo mencionó): no hay absolutamente ninguna garantía de que cuando otro hilo llame a * endApplication() * el valor se leerá como * true * por el hilo que ejecuta el método * run() *. ** Debes ** utilizar algún mecanismo de sincronización aquí, como por ejemplo declarando * terminado * como * volátil *. – TacticalCoder

+0

@Hasslarn: Edité su pregunta y corrigí su código (no es que usar estática de esta manera esté limpio ni nada) agregando * volátil * a su bandera booleana. – TacticalCoder

Respuesta

5

Un problema con el uso de una variable estática en este caso es que si crea dos (o más) instancias de MainLoop, escribir código que parece que está cerrando solo una de las instancias, en realidad apagará ambas. :

MainLoop mainLoop1 = new MainLoop(); 
MainLoop mainLoop2 = new MainLoop(); 

new Thread(mainLoop1).start(); 
new Thread(mainLoop2).start(); 

mainLoop1.finished = true; // static variable also shuts down mainLoop2 

Este es solo un motivo (entre muchos) para elegir no usar variables estáticas. Incluso si su programa de hoy en día solo crea un MainLoop, es posible que en el futuro tenga motivos para crear muchos de ellos: para pruebas unitarias o para implementar una nueva característica interesante.

Puede pensar "si eso sucede alguna vez, simplemente refactorizaré el programa para usar variables miembro en lugar de variables estáticas". Pero generalmente es más eficiente pagar el costo por adelantado, y hornear el diseño modular en el programa desde el principio.

No hay duda de que la estática a menudo hace que un programa rápido y sucio sea más fácil de escribir. Pero para el código importante/complejo que tiene la intención de probar, mantener, crecer, compartir y usar en los próximos años, generalmente se recomiendan las variables estáticas.

Como han señalado otras respuestas a esta pregunta, una variable estática es un tipo de variable global. Y hay mucha información acerca de por qué (generalmente) globalvariablesarebad.

+0

A pesar de que esto se ha dicho antes, me lo dijiste mucho más claro :) –

4

¿Esto es algo que debería evitar?

En general, sí. Las estadísticas representan global estado. El estado global es difícil de razonar, difícil de probar de forma aislada y, en general, tiene mayores requisitos de seguridad de subprocesos.

Si quiero probar lo que ocurre con un objeto en cierto estado, puedo simplemente crear el objeto, ponerlo en ese estado, realizar las pruebas y dejar que se recoja la basura.

Si quiero probar lo que ocurre con el estado global, necesito asegurarme de que reinicié todo al final de mi prueba (o posiblemente al comienzo de cada prueba). Las pruebas ahora interferirán entre sí si no tengo cuidado de hacer eso.

Por supuesto, si el método estático no necesita afectar ningún estado - es decir, si es puro - entonces se vuelve algo mejor. En ese momento, todo lo que está perdiendo es la capacidad de de reemplazar esa implementación de método, p. cuando prueba algo que lo llama.

6

Sí, es mejor pasar los objetos. Usar un singleton o métodos estáticos hace que la programación de OO se vea como una programación de procedimientos. Un singleton es algo mejor porque al menos puede hacer que implemente interfaces o extienda una clase abstracta, pero generalmente es un olor de diseño.

Y mezclar métodos de instancia con variables estáticas como lo está haciendo es aún más confuso: puede tener varios objetos en bucle, pero los detiene todos a la vez porque todos se detienen cuando cambia una variable estática.

2

En general, al hacer finished estático así crea una situación en la que solo puede haber una instancia de su clase MainLoop ejecutando run en cualquier momento. Si hay más de una instancia, al configurar finished se terminarán todas, no lo que es normalmente deseado.

Sin embargo, en este particular, escenario, donde desea "aplicación final", refiriéndose probablemente desea finalizar todas las instancias de MainLoop, el enfoque puede estar justificada.

Sin embargo, el número de situaciones donde este enfoque puede ser merecido son pocas, y una manera "más limpia" de manejar este escenario sería mantener una lista de instancias static y trabajar a través de la lista, estableciendo la variable de instancia finished en cada instancia. Esto le permite también finalizar instancias individuales, le da un recuento natural de las instancias existentes, etc.

+0

Sí, yo mismo en este escenario en particular creo que está justificado, pero podría hacer una expansión de la misma base dura como tú y todo el otros implican. Gracias por el ejemplo de solución –

Cuestiones relacionadas