variable una que modificador estaticas ejemplo diferencia declarar clase java static

java - una - ¿Por qué las variables estáticas son consideradas malas?



variable de clase java (29)

si tuviera que hacer 10,000 llamadas a una función dentro de una clase, me gustaría que el método sea estático y usar un class.methodCall () directo en él en lugar de abarrotar la memoria con 10,000 instancias de la clase, ¿verdad?

Debe equilibrar la necesidad de encapsular datos en un objeto con un estado, frente a la necesidad de simplemente calcular el resultado de una función en algunos datos.

Además, las estadísticas reducen las interdependencias de las otras partes del código.

Lo mismo ocurre con la encapsulación. En aplicaciones grandes, las estáticas tienden a producir código de espagueti y no permiten fácilmente refactorización o prueba.

Las otras respuestas también proporcionan buenas razones contra el uso excesivo de estática.

Soy un programador de Java que es nuevo en el mundo corporativo. Recientemente he desarrollado una aplicación usando Groovy y Java. A lo largo del código que escribí usé una buena cantidad de estadísticas. El lote técnico superior me pidió que redujera la cantidad de estadísticas utilizadas. He buscado en Google lo mismo, y encuentro que muchos programadores están bastante en contra del uso de variables estáticas.

Las variables estáticas me parecen más cómodas de usar. Y supongo que también son eficientes (corríjame si me equivoco), porque si tuviera que hacer 10.000 llamadas a una función dentro de una clase, me gustaría que el método sea estático y utilizar una Class.methodCall() directa Class.methodCall() en él, en lugar de abarrotar la memoria con 10,000 instancias de la clase, ¿verdad?

Además, las estadísticas reducen las interdependencias de las otras partes del código. Pueden actuar como perfectos titulares estatales. Además de esto, encuentro que las estadísticas están ampliamente implementadas en algunos lenguajes como Smalltalk y Scala . Entonces, ¿por qué esta opresión por lo estático prevalece entre los programadores (especialmente en el mundo de Java)?

PD: por favor corríjame si mis suposiciones acerca de lo estático están equivocadas.


a) Motivo de los programas.

Si tiene un programa de tamaño pequeño a mediano, donde se accede a la variable estática Global.foo, la llamada a ella normalmente proviene de la nada, no hay ruta, y por lo tanto no hay una línea de tiempo, cómo la variable llega al lugar, donde se utiliza Ahora, ¿cómo sé quién lo estableció en su valor real? ¿Cómo puedo saber qué pasa si lo modifico ahora? Tengo grep sobre toda la fuente, para recopilar todos los accesos, para saber qué está pasando.

Si sabe cómo lo usa, porque acaba de escribir el código, el problema es invisible, pero si intenta entender el código extranjero, lo entenderá.

b) ¿Realmente solo necesitas uno?

Las variables estáticas a menudo evitan que varios programas del mismo tipo se ejecuten en la misma JVM con diferentes valores. A menudo no prevé usos, donde más de una instancia de su programa es útil, pero si evoluciona, o si es útil para otros, pueden experimentar situaciones en las que les gustaría iniciar más de una instancia de su programa .

Solo el código más o menos inútil que no será utilizado por muchas personas durante más tiempo de forma intensiva podría ir bien con las variables estáticas.


Acabo de resumir algunos de los puntos señalados en las respuestas. Si encuentra algo malo, por favor siéntase libre de corregirlo.

Escalado: tenemos exactamente una instancia de una variable estática por JVM. Supongamos que estamos desarrollando un sistema de gestión de bibliotecas y decidimos poner el nombre del libro como una variable estática ya que solo hay uno por libro. Pero si el sistema crece y estamos usando varias JVM, entonces no tenemos una manera de averiguar con qué libro estamos tratando.

Seguridad de subprocesos: tanto la variable de instancia como la variable estática deben controlarse cuando se utilizan en entornos de subprocesos múltiples. Pero en el caso de una variable de instancia, no necesita protección a menos que se comparta explícitamente entre subprocesos, pero en el caso de una variable estática, siempre es compartida por todos los subprocesos en el proceso.

Pruebas: aunque el diseño comprobable no equivale a un buen diseño, pero rara vez observaremos un buen diseño que no sea comprobable. Como las variables estáticas representan el estado global y es muy difícil probarlas.

Razonamiento sobre el estado: si creo una nueva instancia de una clase, podemos razonar sobre el estado de esta instancia, pero si tiene variables estáticas, podría estar en cualquier estado. ¿Por qué? Debido a que es posible que la variable estática haya sido modificada por alguna instancia diferente, ya que la variable estática se comparte entre las instancias.

Serialización: La serialización tampoco funciona bien con ellos.

Creación y destrucción: la creación y destrucción de variables estáticas no pueden ser controladas. Por lo general, se crean y destruyen en el tiempo de carga y descarga del programa. Esto significa que son malos para la administración de la memoria y también suman el tiempo de inicialización en el inicio.

Pero ¿y si realmente los necesitamos?

Pero a veces podemos tener una necesidad genuina de ellos. Si realmente sentimos la necesidad de muchas variables estáticas que se comparten en la aplicación, entonces una opción es hacer uso del patrón de diseño de Singleton que tendrá todas estas variables. O podemos crear algún objeto que tenga estas variables estáticas y se pueda pasar.

Además, si la variable estática se marca como final, se convierte en una constante y el valor que se le asigna una vez no se puede cambiar. Significa que nos salvará de todos los problemas que enfrentamos debido a su mutabilidad.


Como nadie * lo ha mencionado: concurrencia. Las variables estáticas pueden sorprenderte si tienes varios subprocesos que leen y escriben en la variable estática. Esto es común en las aplicaciones web (por ejemplo, ASP.NET) y puede causar algunos errores bastante enloquecedores. Por ejemplo, si tiene una variable estática que se actualiza con una página y dos personas la solicitan "casi al mismo tiempo", un usuario puede obtener el resultado esperado por el otro, o peor.

Las estadísticas reducen las interdependencias en las otras partes del código. Pueden actuar como perfectos titulares estatales.

Espero que estés preparado para usar cerraduras y lidiar con la contención.

* En realidad, Preet Sangha lo mencionó.


El mal es un término subjetivo.

No controlas lo estático en términos de creación y destrucción. Viven a instancias del programa de carga y descarga.

Dado que las estadísticas están en un solo espacio, todos los subprocesos que deseen usarlas deben pasar por el control de acceso que debe administrar. Esto significa que los programas están más acoplados y este cambio es más difícil de imaginar y administrar (como dice J Skeet). Esto conduce a problemas para aislar el impacto del cambio y, por lo tanto, afecta la forma en que se gestionan las pruebas.

Estos son los dos problemas principales que tengo con ellos.


En mi opinión, casi nunca se trata de rendimiento, se trata de diseño. No considero incorrecto el uso de métodos estáticos como lo es el uso de variables estáticas (pero supongo que en realidad se trata de llamadas a métodos).

Es simplemente sobre cómo aislar la lógica y darle un buen lugar. A veces eso justifica el uso de métodos estáticos de los que java.lang.Math es un buen ejemplo. Creo que cuando nombre la mayoría de sus clases XxxUtil o Xxxhelper es mejor que reconsidere su diseño.


Hay 2 problemas principales con las variables estáticas:

  • Seguridad de subprocesos: los recursos estáticos no son, por definición, seguros para subprocesos
  • Implicidad del código: no se sabe cuándo se crea una instancia de una variable estática y si se creará o no una instancia de otra variable estática

Las variables estáticas generalmente se consideran malas porque representan un estado global y, por lo tanto, son mucho más difíciles de razonar. En particular, rompen los supuestos de la programación orientada a objetos. En la programación orientada a objetos, cada objeto tiene su propio estado, representado por variables de instancia (no estáticas). Las variables estáticas representan el estado en todas las instancias, lo que puede ser mucho más difícil de probar por unidad. Esto se debe principalmente a que es más difícil aislar los cambios de las variables estáticas en una sola prueba.

Dicho esto, es importante hacer una distinción entre las variables estáticas regulares (generalmente consideradas malas) y las variables estáticas finales (constantes AKA; no tan malas).


Las variables estáticas representan el estado global. Es difícil razonar y difícil probar: si creo una nueva instancia de un objeto, puedo razonar sobre su nuevo estado dentro de las pruebas. Si uso código que utiliza variables estáticas, podría estar en cualquier estado, y cualquier cosa podría estar modificándolo.

Podría seguir por un buen rato, pero el concepto más importante a tener en cuenta es que cuanto más ajustado sea el alcance de algo, más fácil será razonar. Somos buenos pensando en cosas pequeñas, pero es difícil razonar sobre el estado de un sistema de un millón de líneas si no hay modularidad. Por cierto, esto se aplica a todo tipo de cosas, no solo a variables estáticas.


Las variables estáticas, lo más importante, crean problemas con la seguridad de los datos (cada vez que cambian, cualquiera puede cambiar, acceso directo sin objeto, etc.)

Para más información lea this Gracias.


Me parece que estás preguntando acerca de las variables estáticas, pero también señala los métodos estáticos en tus ejemplos.

Las variables estáticas no son malas, tienen su adopción como variables globales como constantes en la mayoría de los casos combinados con el modificador final, pero como se dice no se deben usar en exceso.

Métodos estáticos también conocido como método de utilidad. Generalmente no es una mala práctica usarlos, pero la mayor preocupación es que podrían obstruct pruebas.

Como ejemplo de un gran proyecto java que usa muchas estadísticas y lo hace de forma correcta, ¡mire Play! marco También hay discussion respecto en SO.

Las variables / métodos estáticos combinados con la importación estática también se usan ampliamente en las bibliotecas que facilitan la programación declarativa en java como: lo hacen fácil o Hamcrest . No sería posible sin muchas variables y métodos estáticos.

Así que las variables estáticas (y los métodos) son buenas, ¡pero utilícelas sabiamente!


No. Los estados globales no son malos per se. Pero tenemos que ver su código para ver si lo usó correctamente. Es muy posible que un novato abusa de estados globales; Al igual que él abusaría de cada característica del idioma.

Los estados globales son una necesidad absoluta. No podemos evitar estados globales. No podemos evitar el razonamiento sobre estados globales. - Si nos importa entender nuestra semántica de la aplicación.

Las personas que intentan deshacerse de los estados globales por el bien de ellos, inevitablemente terminan con un sistema mucho más complejo, y los estados globales siguen ahí, disfrazados de forma inteligente / idiotas bajo muchas capas de indirectas; y todavía tenemos que razonar acerca de los estados globales, después de desenvolver todas las indirecciones.

Al igual que la gente de Spring, quienes declaran generosamente estados globales en xml y piensan de alguna manera que es superior.

@Jon Skeet, if I create a new instance of an object ahora tiene dos razones para razonar: el estado dentro del objeto y el estado del entorno que alberga el objeto.


Otra razón más: la fragilidad.

Si tiene una clase, la mayoría de la gente espera poder crearla y usarla a voluntad.

Puede documentar que no es el caso, o protegerse contra él (patrón de fábrica / singleton), pero eso es un trabajo adicional y, por lo tanto, un costo adicional. Incluso entonces, en una gran empresa, es probable que alguien intente en algún momento usar su clase sin prestar atención a todos los buenos comentarios o la fábrica.

Si estás usando mucho las variables estáticas, eso se romperá. Los insectos son caros.

Entre una mejora del rendimiento de .0001% y la solidez para cambiar por parte de desarrolladores potencialmente despistados, en muchos casos la solidez es la mejor opción.


Se puede sugerir que en la mayoría de los casos en los que utiliza una variable estática, realmente desea utilizar el patrón de singleton .

El problema con los estados globales es que a veces lo que tiene sentido como global en un contexto más simple, necesita ser un poco más flexible en un contexto práctico, y aquí es donde el patrón de singleton se vuelve útil.


Si está utilizando la palabra clave ''estática'' sin la palabra clave ''final'', esto debe ser una señal para considerar cuidadosamente su diseño. Incluso la presencia de un ''final'' no es un pase libre, ya que un objeto final estático mutable puede ser igual de peligroso.

Estimaría que en algún lugar alrededor del 85% del tiempo veo un ''estático'' sin un ''final'', es INCORRECTO. A menudo, encontraré soluciones extrañas para ocultar u ocultar estos problemas.

Por favor no cree objetos estáticos. Especialmente las colecciones. En general, las colecciones deben inicializarse cuando se inicializa su objeto contenedor y deben diseñarse de modo que se reinicien u olviden cuando se olvide su objeto contenedor.

El uso de estadísticas estáticas puede crear errores muy sutiles que causarán a los ingenieros días de dolor. Lo sé, porque he creado y cazado estos errores.

Si desea más detalles, siga leyendo ...

¿Por qué no usar estática?

Hay muchos problemas con las estadísticas, como escribir y ejecutar pruebas, así como errores sutiles que no son evidentes de inmediato.

El código que se basa en objetos estáticos no se puede probar fácilmente por unidad, y las estadísticas no se pueden burlar fácilmente (generalmente).

Si utiliza estadísticas, no es posible intercambiar la implementación de la clase para probar componentes de nivel superior. Por ejemplo, imagine un CustomerDAO estático que devuelve los objetos del Cliente que carga de la base de datos. Ahora tengo una clase CustomerFilter, que necesita acceder a algunos objetos del Cliente. Si CustomerDAO es estático, no puedo escribir una prueba para CustomerFilter sin inicializar primero mi base de datos y llenar información útil.

Y la base de datos de la población y la inicialización lleva mucho tiempo. Y, según mi experiencia, el marco de inicialización de su base de datos cambiará con el tiempo, lo que significa que los datos se transformarán y las pruebas se romperán. IE, imagine que el Cliente 1 solía ser un VIP, pero el marco de inicialización de la base de datos cambió, y ahora el Cliente 1 ya no es VIP, pero su prueba fue codificada para cargar el Cliente 1 ...

Un mejor enfoque es crear una instancia de un CustomerDAO y pasarlo al CustomerFilter cuando se construye. (Un enfoque aún mejor sería utilizar Spring u otro marco de Inversión de control.

Una vez que haga esto, puede simular o apagar rápidamente un DAO alternativo en su Prueba de filtro de clientes, lo que le permite tener más control sobre la prueba.

Sin el DAO estático, la prueba será más rápida (sin inicialización db) y más confiable (porque no fallará cuando cambie el código de inicialización db). Por ejemplo, en este caso, garantizar que el Cliente 1 es y siempre será un VIP, en lo que respecta a la prueba.

Pruebas de ejecución

Las estadísticas causan un problema real cuando se ejecutan conjuntos de pruebas unitarias (por ejemplo, con su servidor de integración continua). Imagine un mapa estático de objetos Socket de red que permanece abierto de una prueba a otra. La primera prueba podría abrir un Socket en el puerto 8080, pero se olvidó de borrar el Mapa cuando se rompe la prueba. Ahora, cuando se inicia una segunda prueba, es probable que se bloquee cuando intenta crear un nuevo Socket para el puerto 8080, ya que el puerto todavía está ocupado. Imagine también que las referencias de Socket en su colección estática no se eliminan y (con la excepción de WeakHashMap) nunca son elegibles para la recolección de basura, lo que provoca una pérdida de memoria.

Este es un ejemplo generalizado, pero en sistemas grandes, este problema ocurre TODO EL TIEMPO. La gente no piensa que las pruebas unitarias inicien y detengan su software repetidamente en la misma JVM, pero es una buena prueba de su diseño de software, y si tiene aspiraciones de alta disponibilidad, es algo que debe tener en cuenta.

Estos problemas a menudo surgen con los objetos del marco, por ejemplo, el acceso a la base de datos, el almacenamiento en caché, la mensajería y las capas de registro. Si está utilizando Java EE o algunos de los mejores marcos genéricos, es probable que manejen mucho de esto por usted, pero si, como yo, está tratando con un sistema heredado, es posible que tenga muchos marcos personalizados para acceder a estas capas.

Si la configuración del sistema que se aplica a estos componentes del marco cambia entre las pruebas unitarias, y el marco de la prueba unitaria no destruye y reconstruye los componentes, estos cambios no tendrán efecto, y cuando una prueba se base en esos cambios, fallará .

Incluso los componentes que no son del marco están sujetos a este problema. Imagina un mapa estático llamado OpenOrders. Usted escribe una prueba que crea unas pocas órdenes abiertas, y verifica que todas estén en el estado correcto, y luego la prueba termina. Otro desarrollador escribe una segunda prueba que coloca los pedidos que necesita en el mapa de OpenOrders, luego afirma que el número de pedidos es exacto. Ejecutadas individualmente, estas pruebas pasarían a la vez, pero cuando se ejecuten juntas en una suite, fallarán.

Peor aún, la falla podría estar basada en el orden en que se ejecutaron las pruebas.

En este caso, al evitar lo estático, evita el riesgo de que los datos persistan en las instancias de prueba, lo que garantiza una mejor confiabilidad de la prueba.

Bichos sutiles

Si trabaja en un entorno de alta disponibilidad, o en cualquier lugar donde los subprocesos puedan iniciarse y detenerse, la misma preocupación mencionada anteriormente con las unidades de prueba unitarias puede aplicarse cuando su código también se está ejecutando en producción.

Cuando se trata de subprocesos, en lugar de usar un objeto estático para almacenar datos, es mejor usar un objeto inicializado durante la fase de inicio del subproceso. De esta manera, cada vez que se inicia el subproceso, se crea una nueva instancia del objeto (con una configuración potencialmente nueva), y evita los datos de una instancia del subproceso de sangrado hasta la siguiente instancia.

Cuando un hilo muere, un objeto estático no se restablece ni se recolecta la basura. Imagina que tienes un hilo llamado "EmailCustomers", y cuando se inicia, llena una colección de cadenas estática con una lista de direcciones de correo electrónico, y luego comienza a enviar por correo electrónico cada una de las direcciones. Digamos que el hilo se interrumpe o se cancela de alguna manera, por lo que su marco de alta disponibilidad reinicia el hilo. Luego, cuando el hilo se inicia, vuelve a cargar la lista de clientes. Pero como la colección es estática, puede conservar la lista de direcciones de correo electrónico de la colección anterior. Ahora algunos clientes pueden recibir correos electrónicos duplicados.

Un aparte: final estático

El uso de "final estático" es efectivamente el equivalente de Java de C #define, aunque existen diferencias técnicas de implementación. AC / C ++ #define es intercambiado fuera del código por el preprocesador, antes de la compilación. Una "final estática" de Java terminará en la memoria residente en la pila. De esa manera, es más similar a una variable "estática estática" en C ++ que a una #define.

Resumen

Espero que esto ayude a explicar algunas razones básicas por las que las estadísticas son problemáticas. Si está utilizando un marco Java moderno como Java EE o Spring, etc., es posible que no encuentre muchas de estas situaciones, pero si está trabajando con un gran número de códigos heredados, pueden ser mucho más frecuentes.


Las variables estáticas me parecen más cómodas de usar. Y supongo que también son eficientes (corríjame si me equivoco) porque si tuviera que hacer 10.000 llamadas a una función dentro de una clase, me gustaría que el método sea estático y usar una clase directa. en él, en lugar de abarrotar la memoria con 10,000 instancias de la clase, ¿verdad?

Veo lo que piensa, pero un patrón Singleton simple hará lo mismo sin tener que crear una instancia de 10 000 objetos.

se pueden usar métodos estáticos, pero solo para las funciones que están relacionadas con el dominio del objeto y que no necesitan o usan las propiedades internas del objeto.

ex:

public class WaterContainer { private int size; private int brand; ...etc public static int convertToGallon(int liters)... public static int convertToLiters(int gallon)... }


Resumiendo algunas ventajas y desventajas básicas de usar métodos estáticos en Java:

Ventajas:

  1. Accesible globalmente, es decir, no vinculado con ninguna instancia de objeto en particular.
  2. Una instancia por JVM.
  3. Se puede acceder usando el nombre de la clase (No requiere ningún objeto).
  4. Contiene un solo valor aplicable a todas las instancias.
  5. Carga en el inicio de JVM y muere cuando JVM se apaga.
  6. No modifican el estado del objeto.

Desventajas:

  1. Los miembros estáticos son siempre parte del tiempo de memoria que están en uso o no.
  2. No se puede controlar la creación y destrucción de variables estáticas. De manera útil, se crearon en la carga del programa y se destruyeron cuando se descarga el programa (o cuando se apaga la JVM).
  3. Puede hacer que el subproceso estático sea seguro usando la sincronización, pero necesita algunos esfuerzos adicionales.
  4. Si un hilo cambia el valor de una variable estática que posiblemente pueda romper la funcionalidad de otros hilos.
  5. Debes saber "estático" antes de usarlo.
  6. No se pueden anular los métodos estáticos.
  7. La serialización no funciona bien con ellos.
  8. No participan en el polimorfismo en tiempo de ejecución.
  9. Hay un problema de memoria (hasta cierto punto, pero no mucho, supongo) si se utiliza una gran cantidad de variables / métodos estáticos. Porque no serán GC hasta que el programa termine.
  10. Los métodos estáticos también son difíciles de probar.

No está muy orientado a los objetos: una razón por la cual las personas pueden ser consideradas "malas" por algunas personas es que son contrarias al paradigma orientado a objetos . En particular, viola el principio de que los datos se encapsulan en objetos (que se pueden extender, ocultar información, etc.). Las estadísticas, en la forma en que las describe al usarlas, son esencialmente para usarlas como una variable global para evitar tratar temas como el alcance. Sin embargo, las variables globales son una de las características definitorias del paradigma de programación imperativa o de procedimiento, no una característica del código "bueno" orientado a objetos. Esto no quiere decir que el paradigma de procedimiento sea malo, pero tengo la impresión de que su supervisor espera que usted escriba "código orientado a objetos bueno" y que realmente desea escribir "código de procedimiento correcto".

Hay muchos gotchyas en Java cuando empiezas a usar estadísticas que no siempre son inmediatamente obvias. Por ejemplo, si tiene dos copias de su programa ejecutándose en la misma máquina virtual, ¿compartirán el valor de la variable estática y se mezclarán con el estado de cada una? O, ¿qué sucede cuando extiendes la clase? ¿Puedes anular el miembro estático? ¿Se está quedando sin memoria en su máquina virtual porque tiene un número increíble de estadísticas y esa memoria no se puede reclamar para otros objetos de instancia necesarios?

Vida útil del objeto: además, las estadísticas tienen una vida útil que coincide con todo el tiempo de ejecución del programa. Esto significa que, incluso una vez que haya terminado de usar su clase, la memoria de todas esas variables estáticas no puede ser recogida de basura. Si, por ejemplo, en cambio, hizo que sus variables no fueran estáticas, y en su función main () creó una única instancia de su clase y luego le pidió a su clase que ejecutara una función en particular 10,000 veces, una vez que se realizaron esas 10,000 llamadas. , y elimina sus referencias a la instancia única, todas sus variables estáticas podrían ser recolectadas y reutilizadas.

Previene la reutilización de ciertos elementos: Además, los métodos estáticos no se pueden usar para implementar una interfaz, por lo que los métodos estáticos pueden evitar que ciertas características orientadas a objetos sean utilizables.

Otras opciones: Si su principal preocupación es la eficiencia, podría haber otras formas mejores de resolver el problema de la velocidad que considerar que la ventaja de la invocación suele ser más rápida que la creación. Considere si los modificadores transitorios o volátiles son necesarios en cualquier lugar. Para preservar la capacidad de estar en línea, un método podría marcarse como final en lugar de estático. Los parámetros del método y otras variables se pueden marcar como finales para permitir ciertas optimizaciones del compilador basadas en suposiciones sobre lo que puede cambiar esas variables. Un objeto de instancia podría reutilizarse varias veces en lugar de crear una nueva instancia cada vez. Puede haber interruptores de optimización de complementos que deberían estar activados para la aplicación en general. Tal vez, el diseño debería configurarse para que las 10,000 ejecuciones puedan ser multiproceso y aprovechar los núcleos de multiprocesador. Si la portabilidad no es una preocupación, tal vez un método nativo te permita obtener una velocidad mayor que la de tus estadísticas.

Si, por alguna razón, no desea varias copias de un objeto, el patrón de diseño de singleton tiene ventajas sobre los objetos estáticos, como la seguridad de subprocesos (suponiendo que su singleton está bien codificado), lo que permite una inicialización lenta, garantizando que el objeto se ha realizado correctamente. inicializado cuando se usa, subclasificación, ventajas en la prueba y refactorización de su código, por no mencionar, si en algún momento cambia de opinión acerca de querer solo una instancia de un objeto, es MUCHO más fácil eliminar el código para evitar la duplicación de instancias. que refactorizar todo su código de variable estática para usar variables de instancia. He tenido que hacer eso antes, no es divertido, y terminas teniendo que editar muchas más clases, lo que aumenta el riesgo de introducir nuevos errores ... mucho mejor para configurar las cosas "bien" la primera vez, incluso si parece que tiene sus desventajas. Para mí, el trabajo requerido en caso de que decidas por el camino en el que necesitas múltiples copias de algo es probablemente una de las razones más convincentes para usar las estadísticas con la menor frecuencia posible. Y, por lo tanto, tampoco estaría de acuerdo con su afirmación de que las estadísticas reducen las interdependencias. Creo que terminará con un código más acoplado si tiene muchas estadísticas a las que se puede acceder directamente, en lugar de un objeto que "sabe cómo hacerlo". algo "en sí mismo.


Creo que el uso excesivo de variables globales con palabras clave estáticas también conducirá a una pérdida de memoria en algún punto de la aplicación.


Hay dos preguntas principales en tu publicación.

Primero, sobre las variables estáticas. Las variables estáticas son totalmente innecesarias y su uso puede evitarse fácilmente. En lenguajes OOP en general, y en particular en Java, los parámetros de función se pegan por referencia, es decir, si pasa un objeto a una función, está pasando un puntero al objeto, por lo que no necesita definir variables estáticas ya que puede pasar un puntero al objeto a cualquier ámbito que necesite esta información. Incluso si esto implica que usted llenará su memoria con punteros, esto no necesariamente representará un bajo rendimiento porque los sistemas de paginación de memoria reales están optimizados para manejar esto, y mantendrán en la memoria las páginas a las que hacen referencia los punteros que pasó a la nueva alcance;el uso de variables estáticas puede hacer que el sistema cargue la página de memoria donde se almacenan cuando es necesario acceder a ellas (esto ocurrirá si no se ha accedido a la página durante mucho tiempo). Una buena práctica es poner todas esas cosas estáticas juntas en algunas pequeñas "clases de configuración", esto asegurará que el sistema lo coloque todo en la misma página de memoria.

Segundo, sobre los métodos estáticos. Los métodos estáticos no son tan malos, pero pueden reducir rápidamente el rendimiento. Por ejemplo, piense en un método que compare dos objetos de una clase y devuelva un valor que indique cuál de los objetos es más grande (método de comparación típico) este método puede ser estático o no, pero al invocarlo, la forma no estática será más eficiente ya que solo tendrá que resolver dos referencias (una para cada objeto) frente a las tres referencias que deberán resolver la versión estática del mismo método (una para la clase más dos, una para cada objeto). Pero como digo, esto no es tan malo, si echamos un vistazo a la clase de Matemáticas, podemos encontrar muchas funciones matemáticas definidas como métodos estáticos. Esto es realmente más eficiente que poner todos estos métodos en la clase que define los números,Debido a que la mayoría de ellos son raramente usados ​​e incluirlos a todos en la clase de números hará que la clase sea muy compleja y consuma muchos recursos innecesariamente.

En conclusión: evite el uso de variables estáticas y encuentre el equilibrio de rendimiento correcto cuando trate con métodos estáticos o no estáticos.

PD: perdon por mi ingles


Hay un montón de buenas respuestas aquí, añadiendo a esto,

Memoria: las variables estáticas están activas mientras el cargador de clases esté activo [en general, hasta que la VM muere], pero esto solo ocurre en el caso de objetos / referencias a granel almacenados como estáticos.

Modularización: considere conceptos como IOC, dependencyInjection, proxy, etc. Todos están completamente en contra de las implementaciones de acoplamiento / estática.

Otras Con''s: Seguridad de Hilos, Probabilidad


Mi $ .02 es que varias de estas respuestas confunden el problema, en lugar de decir "lo estático es malo", creo que es mejor hablar sobre el alcance y las instancias.

Lo que diría es que una variable estática es una variable de "clase": representa un valor que se comparte en todas las instancias de esa clase. Por lo general, también se debe incluir en ese ámbito (protegido o privado a la clase y sus instancias).

Si planea poner un comportamiento de clase a su alrededor y exponerlo a otro código, entonces un singleton puede ser una mejor solución para soportar cambios en el futuro (como sugirió @Jessica). Esto se debe a que puede usar interfaces en el nivel de instancia / singleton en formas que no puede usar en el nivel de clase, en particular la herencia.

Algunas reflexiones sobre por qué creo que algunos de los aspectos de otras respuestas no son fundamentales para la pregunta ...

Las estadísticas no son "globales". En Java, el alcance se controla por separado de static / instance.

La concurrencia no es menos peligrosa para los métodos estáticos que los métodos de instancia. Todavía es el estado que necesita ser protegido. Claro que puede tener 1000 instancias con una variable de instancia cada una y solo una variable estática, pero si el acceso al código no está escrito de forma segura, todavía puede fallar, solo puede tardar un poco más en darse cuenta. .

La gestión del ciclo de vida es un argumento interesante, pero creo que es menos importante. No veo por qué es más difícil administrar un par de métodos de clase como init () / clear () que la creación y destrucción de una instancia de singleton. De hecho, algunos podrían decir que un singleton es un poco más complicado debido a GC.

PD: en términos de Smalltalk, muchos de sus dialectos tienen variables de clase, pero en Smalltalk las clases son en realidad instancias de Metaclass, así que realmente son variables en la instancia de Metaclass. Aún así, yo aplicaría la misma regla de oro. Si se están utilizando para el estado compartido entre instancias, entonces está bien. Si son compatibles con la funcionalidad pública, debería mirar un Singleton. Suspiro, seguro que echo de menos Smalltalk ...


Piense que si tiene una aplicación con muchos usuarios y ha definido un formulario estático, entonces todos los usuarios modificarán todas las demás formas de otros usuarios también.


Desde mi punto de vista, la staticvariable debería ser solo lectura de datos o variables creadas por convención .

Por ejemplo, tenemos una interfaz de usuario de algún proyecto, y tenemos una lista de países, idiomas, roles de usuario, etc. Y tenemos clase para organizar estos datos. Estamos absolutamente seguros de que la aplicación no funcionará sin estas listas. así que lo primero que hacemos en la aplicación init es buscar actualizaciones en esta lista y obtener esta lista de la API (si es necesario). Así que estamos de acuerdo en que estos datos están "siempre" presentes en la aplicación. Prácticamente solo se leen datos, por lo que no necesitamos ocuparnos de su estado. Pensando en este caso, realmente no queremos tener muchos ejemplos de esos datos; este caso parece un candidato perfecto para ser estático .


El tema de ''Estática es malvado'' es más un problema sobre el estado global. El momento adecuado para que una variable sea estática es si nunca tiene más de un estado; Las herramientas de IE que deberían ser accesibles por todo el marco y siempre devolver los mismos resultados para las mismas llamadas de métodos nunca son "malas" como las estadísticas. En cuanto a tu comentario:

Las variables estáticas me parecen más cómodas de usar. Y supongo que también son eficientes.

Las estadísticas son la opción ideal y eficiente para las variables / clases que nunca cambian .

El problema con el estado global es la incoherencia inherente que puede crear. La documentación acerca de las pruebas unitarias a menudo aborda este problema, ya que cada vez que hay un estado global al que se puede acceder por más de múltiples objetos no relacionados, sus pruebas unitarias estarán incompletas y no serán integradas por la unidad. Como se menciona en este artículo sobre el estado global y singletons , si el objeto A y B no están relacionados (ya que en uno no se hace referencia expresa a otro), A no debería poder afectar el estado de B.

Hay algunas excepciones al estado global de prohibición en un buen código, como el reloj. El tiempo es global y, en cierto sentido, cambia el estado de los objetos sin tener una relación codificada.


Las variables estáticas no son buenas ni malas. Representan atributos que describen a toda la clase y no a una instancia en particular. Si necesita tener un contador para todas las instancias de una determinada clase, una variable estática sería el lugar correcto para mantener el valor.

Los problemas aparecen cuando intenta utilizar variables estáticas para mantener valores relacionados con la instancia.


No hay nada malo con las variables estáticas per se. Es solo la sintaxis de Java que está rota. Cada clase de Java realmente define dos estructuras: un objeto singleton que encapsula variables estáticas y una instancia. Definir ambos en el mismo bloque de origen es simplemente malvado y da como resultado un código que es difícil de leer. Scala lo hizo bien.


Todas las respuestas anteriores muestran por qué las estadísticas son malas. La razón por la que son malvados es porque da la falsa impresión de que está escribiendo código orientado a objetos, cuando en realidad no lo está. Eso es simplemente el mal.


todo (puede :) tiene su propósito, si tiene un montón de subprocesos que necesitan compartir / almacenar datos en caché y también toda la memoria accesible (para no dividirse en contextos dentro de una JVM) la estática es la mejor opción

-> por supuesto que puede forzar sólo una instancia, pero ¿por qué?
Encuentro algunos de los comentarios en este hilo mal, no los estáticos;)