valor usar objetos metodos metodo llamar estático estaticos estatico estaticas definicion cuando contexto como clases atributo java static methods static-methods

java - usar - objetos estaticos definicion



¿Deben los métodos de ayuda privada ser estáticos si pueden ser estáticos? (21)

o alguna razón en particular para no [declararlos como estáticos]?

Sí.

Al mantenerlos como métodos de instancia, te permites proporcionar una implementación diferente más adelante.

Puede sonar tonto (y de hecho lo sería si esos métodos son utilizados solo por usted en un programa de 50 líneas) pero en aplicaciones más grandes, o en bibliotecas usadas por otra persona, puede decidir elegir una mejor implementación, pero no lo haga. quiero romper el código existente

Así que creas una subclase y la devuelves en las nuevas versiones, y como los métodos se declararon como métodos de instancia, simplemente dejas que el polimorfismo haga su trabajo.

Además, podría beneficiarse de hacer que el constructor sea privado y proporcionar un método de fábrica estático por el mismo motivo.

Por lo tanto, mi recomendación es mantenerlos como métodos de instancia y evitar la estática si es posible.
Aproveche el dinamismo que proporciona el idioma.

Vea aquí un video algo relacionado: cómo diseñar una buena API y por qué es importante

Aunque no está directamente relacionado con la discusión del método "static vs instance", toca algunos puntos interesantes en el diseño de la API.

Digamos que tengo una clase diseñada para ser instanciada. Tengo varios métodos privados de "ayuda" dentro de la clase que no requieren acceso a ninguno de los miembros de la clase, y operan únicamente en sus argumentos, devolviendo un resultado.

public class Example { private Something member; public double compute() { double total = 0; total += computeOne(member); total += computeMore(member); return total; } private double computeOne(Something arg) { ... } private double computeMore(Something arg) {... } }

¿Hay alguna razón particular para especificar computeOne y computeMore como métodos estáticos o alguna razón particular para no hacerlo?

Sin duda, es más fácil dejarlos como no estáticos, a pesar de que ciertamente podrían ser estáticos sin causar ningún problema.


  1. Sin el modificador estático, no puede darse cuenta de que el método es sin estado sin un análisis adicional que puede hacerse fácilmente cuando (re) escribe el método.

  2. Entonces, el modificador "estático" puede darle ideas sobre refactorización además de otras cosas que otros pueden considerar inútiles. Por ejemplo, mover el método a alguna clase de Utilidad o convertirlo en un método miembro.


Como mucha gente dijo, ¡hazlo como estático ! Esta es la regla general que sigo: si crees que el método es solo una función matemática, es decir, no tiene estado, no implica ninguna variable de instancia (=> no vars de color azul [en eclipse] en el método), y el resultado de el método será el mismo para ''n'' número de llamadas (con los mismos parámetros, por supuesto), luego marque ese método como ESTÁTICO.

Y si cree que este método será útil para otra clase, muévalo a una clase Util de lo contrario, coloque el método como privado en la misma clase. (minimizando el acceso)


De la experiencia, afirmaría que tales métodos privados tienden a ser bastante universales y reutilizables.

Creo que lo primero que debemos hacer es preguntarnos si el método puede ser útil fuera del contexto de clase actual. Si es así, haría exactamente lo que todos sugieren y extraeré este método como estático para alguna clase de utils donde alguien espere que revise antes de implementar un nuevo método haciendo exactamente lo mismo.

Dichos métodos privados de uso general son fuente de gran parte de la duplicación de código en el proyecto porque cada desarrollador los reinventa de forma independiente en el lugar donde necesita usarlo. Entonces, la centralización de tales métodos es un camino por recorrer.


Fuera de tema: mantendría los métodos de ayuda en una clase de utilidad / ayudante independiente con solo métodos estáticos en ella.

El problema de tener métodos de ayuda en el punto de uso (léase ''la misma clase'') es que alguien más adelante puede simplemente elegir publicar sus propios métodos auxiliares no relacionados en el mismo lugar.


La pregunta estática / no estática se reduce a "¿Realmente necesitaré usar un objeto de esta clase"?

Entonces, ¿pasas el objeto entre diferentes métodos? ¿El objeto contiene información que es útil fuera del contexto de los métodos estáticos? ¿Hay alguna razón para no definir los métodos en ambos sentidos si los usará en ambos sentidos?

Si estás en este dilema, me parece que tienes todos los datos necesarios para que el método flote en tu código fuera del objeto. ¿Es esto lo que quieres? ¿Sería más fácil simplemente recopilar siempre esos datos en un objeto cada vez? Puede ser ambivalente acerca de comprometerse con un modelo único. Si puede hacerlo todo de una sola manera, elija entre estático o no estático y vaya con él.


La respuesta correcta es:

cualquier método que no tome información de un campo y no incluya información en un campo, no tiene que ser un método de instancia. Cualquier método que no use o altere ningún campo en su clase u objeto también podría ser un método estático.


La respuesta es, depende.

Si el miembro es una variable de instancia específica del objeto con el que está tratando, ¿por qué pasarlo como parámetro?

Por ejemplo:

public class Example { private Something member; public double compute() { double total = 0; total += computeOne(); total += computeMore(); return total; } private double computeOne() { /* Process member here */ } private double computeMore() { /* Process member here */ } }


Los declararía como estáticos para señalarlos como sin estado.

Java no tiene un mecanismo mejor para operaciones menores que no se exportan, así que creo que la estática privada es aceptable.


Más específicamente al ejemplo que usted ha dado, parece que el propósito de definir estos métodos es más por la claridad del código cuando lo está leyendo que por la funcionalidad (se definen como privados). En ese caso, ir con estática realmente no hace nada por ti, ya que el propósito de la estática es exponer la funcionalidad de la clase.


Me gustaría aclarar algunas cosas que otros carteles han dicho ya que dan información incorrecta.

En primer lugar, dado que los métodos son privados, incluso si los declara estáticos, no podrá acceder a ellos fuera de esta clase. En segundo lugar, son privados, por lo que no se puede anular en la subclase, por lo que la estática o no estática no hace ninguna diferencia. En tercer lugar, también se puede llamar a un método privado no estático desde un constructor de la clase, no necesita ser estático.

Ahora vamos a su pregunta si un método de ayuda privada debe definirse como estático o no estático. Iré con la respuesta de Steve ya que al marcar un método privado estático muestra que este método es sin estado ya que también sigo esta regla cuando codigo.


Mi preferencia en casos como estos es hacer computeOne y computeMore métodos estáticos. La razón: encapsulación. Cuanto menos código tenga acceso a la implementación de su clase, mejor.

En el ejemplo que usted da, usted computeOne que computeOne y computeMore no deberían necesitar acceder a las computeMore internas de la clase, entonces, ¿por qué darles la oportunidad a los mantenedores de la clase de entrometerse con las partes internas?


Mi preferencia personal sería declararlas estáticas, ya que es una clara señal de que son apátridas.


Prefiero que tales métodos de ayuda sean private static ; que dejará en claro al lector que no modificarán el estado del objeto. Mi IDE también mostrará las llamadas a métodos estáticos en cursiva, así sabré que el método es estático sin buscar la firma.


Puede dar como resultado un bytecode ligeramente más pequeño, ya que los métodos estáticos no tendrán acceso a this . No creo que haga ninguna diferencia en la velocidad (y si lo hiciera, probablemente sería demasiado pequeño para marcar una diferencia en general).

Los haría estáticos, ya que generalmente lo hago si es posible. Pero solo soy yo.

EDITAR: Esta respuesta sigue siendo downvoted, posiblemente debido a la afirmación sin fundamento sobre el tamaño del bytecode. Entonces, realmente ejecutaré una prueba.

class TestBytecodeSize { private void doSomething(int arg) { } private static void doSomethingStatic(int arg) { } public static void main(String[] args) { // do it twice both ways doSomethingStatic(0); doSomethingStatic(0); TestBytecodeSize t = new TestBytecodeSize(); t.doSomething(0); t.doSomething(0); } }

Bytecode (recuperado con javap -c -private TestBytecodeSize ):

Compiled from "TestBytecodeSize.java" class TestBytecodeSize extends java.lang.Object{ TestBytecodeSize(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return private void doSomething(int); Code: 0: return private static void doSomethingStatic(int); Code: 0: return public static void main(java.lang.String[]); Code: 0: iconst_0 1: invokestatic #2; //Method doSomethingStatic:(I)V 4: iconst_0 5: invokestatic #2; //Method doSomethingStatic:(I)V 8: new #3; //class TestBytecodeSize 11: dup 12: invokespecial #4; //Method "<init>":()V 15: astore_1 16: aload_1 17: iconst_0 18: invokespecial #5; //Method doSomething:(I)V 21: aload_1 22: iconst_0 23: invokespecial #5; //Method doSomething:(I)V 26: return }

La invocación del método estático requiere dos códigos de bytes (byteops?): iconst_0 (para el argumento) e invokestatic .
Invocar el método no estático requiere tres: aload_1 (para el objeto TestBytecodeSize , supongo), iconst_0 (para el argumento) e invokespecial . (Tenga en cuenta que si estos no hubieran sido métodos privados, se habría invokevirtual lugar de invokespecial , consulte JLS §7.7 Invocar métodos ).

Ahora, como dije, no espero que exista una gran diferencia en el rendimiento entre estos dos, aparte del hecho de que invokestatic requiere un bytecode menos. invokestatic e invokespecial deberían ser ligeramente más rápidos que invokevirtual , ya que ambos usan enlace estático en lugar de dinámico, pero no tengo idea si alguno es más rápido que el otro. No puedo encontrar ninguna buena referencia tampoco. Lo más cercano que puedo encontrar es este artículo de JavaWorld de 1997 , que básicamente reafirma lo que acabo de decir:

Las instrucciones más rápidas probablemente serán invokespecial e invokestatic , porque los métodos invocados por estas instrucciones están vinculados estáticamente. Cuando la JVM resuelve la referencia simbólica para estas instrucciones y la reemplaza con una referencia directa, esa referencia directa probablemente incluirá un puntero a los códigos de byte reales.

Pero muchas cosas han cambiado desde 1997.

Entonces, en conclusión ... creo que todavía estoy apegándome a lo que dije antes. La velocidad no debería ser la razón para elegir una sobre la otra, ya que sería una micro-optimización en el mejor de los casos.


Realmente no puedo pensar en claras ventajas para el método estático privado. Dicho esto, no hay ventajas específicas para hacerlos no estáticos tampoco. Se trata principalmente de una cuestión de presentación: es posible que desee que sean estáticos para subrayar claramente el hecho de que no están alterando un objeto.

Para el método con diferentes privilegios de acceso, creo que hay dos argumentos principales:

  • Se pueden invocar métodos estáticos sin crear una instancia de un objeto, lo que puede ser útil
  • los métodos estáticos no pueden heredarse, lo que puede ser un problema si necesita un polimorfismo (pero es irrelevante para los métodos privados).

Además de eso, la diferencia es bastante pequeña, y dudo mucho que el extra que este puntero pasó al método de instancia marque una diferencia significativa.


Si el método es básicamente una subrutina que nunca usará información de estado, declare que estática.

Esto le permite ser utilizado en otros métodos estáticos o en la inicialización de la clase, es decir:

public class Example { //... //Only possible if computeOne is static public final static double COMPUTED_ONE = computeOne(new Something("1")); //... }


Un problema con tener métodos estáticos es que puede hacer que el objeto sea más difícil de usar en pruebas unitarias . Mockito no puede crear simulaciones para métodos estáticos y no puede crear una implementación de subclase del método.


Una razón es que, si todo lo demás es igual, las llamadas a métodos estáticos deberían ser más rápidas. Los métodos estáticos no pueden ser virtuales y no toman una referencia implícita.


Una razón por la que puede querer declarar métodos estáticos de ayuda es si necesita llamarlos en el constructor de la clase "antes" de this o super . Por ejemplo:

public class MyClass extends SomeOtherClass { public MyClass(String arg) { super(recoverInt(arg)); } private static int recoverInt(String arg) { return Integer.parseInt(arg.substring(arg.length() - 1)); } }

Este es un pequeño ejemplo inventado, pero claramente recoverInt no puede ser un método de instancia en este caso.


class Whatever { public static varType myVar = initializeClassVariable(); private static varType initializeClassVariable() { //initialization code goes here } }

La ventaja de los métodos estáticos privados es que pueden reutilizarse más adelante si necesita reinicializar la variable de clase.