Digamos que tengo una clase diseñada para ser instanciada. Tengo varios métodos privados "auxiliares" dentro de la clase que no requieren acceso a ninguno de los miembros de la clase y operan únicamente con 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, aunque ciertamente podrían ser estáticos sin causar ningún problema.
java
static
methods
static-methods
avalys
fuente
fuente
Respuestas:
Prefiero que tales métodos de ayuda sean
private static
; lo que dejará en claro al lector que no modificarán el estado del objeto. Mi IDE también mostrará llamadas a métodos estáticos en cursiva, por lo que sabré que el método es estático sin buscar la firma.fuente
protected static
que los hace verificables muy fácilmente en una clase de prueba en el mismo paquete.static
(si solo lo queremos para probar).Puede resultar en un código de bytes ligeramente más pequeño, ya que los métodos estáticos no tendrán acceso
this
. No creo que haga ninguna diferencia en la velocidad (y si lo hiciera, probablemente sería demasiado pequeño para hacer 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 rechazada, posiblemente debido a la afirmación no confirmada sobre el tamaño del código de bytes. Así que realmente haré una prueba.
Bytecode (recuperado con
javap -c -private TestBytecodeSize
):Invocar el método estático requiere dos bytecodes (byteops?):
iconst_0
(Para el argumento) yinvokestatic
.Invocar el método no estático requiere tres:
aload_1
(para elTestBytecodeSize
objeto, supongo),iconst_0
(para el argumento) yinvokespecial
. (Tenga en cuenta que si estos no hubieran sido métodos privados, lo habría sido eninvokevirtual
lugar deinvokespecial
; consulte JLS §7.7 Métodos de invocación ).Ahora, como dije, no espero que haya una gran diferencia en el rendimiento entre estos dos, aparte del hecho de que
invokestatic
requiere un código de bytes menos.invokestatic
yinvokespecial
ambos deberían ser un poco más rápidos queinvokevirtual
, 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. Tampoco puedo encontrar buenas referencias. Lo más cercano que puedo encontrar es este artículo de JavaWorld de 1997 , que básicamente repite lo que acabo de decir:Pero muchas cosas han cambiado desde 1997.
En conclusión ... Supongo que todavía me quedo con lo que dije antes. La velocidad no debería ser la razón para elegir uno sobre el otro, ya que sería una micro optimización en el mejor de los casos.
fuente
Mi preferencia personal sería declararlos estáticos, ya que es una clara señal de que no tienen estado.
fuente
La respuesta es, depende.
Si miembro es una variable de instancia específica del objeto con el que está tratando, ¿por qué pasarla como parámetro?
Por ejemplo:
fuente
Una razón por la que es posible que desee declarar métodos auxiliares estáticos es si necesita llamarlos en el constructor de la clase "antes"
this
osuper
. Por ejemplo:Este es un ejemplo un poco artificial, pero claramente
recoverInt
no puede ser un método de instancia en este caso.fuente
Realmente no puedo pensar en ventajas claras para el método estático privado. Dicho esto, tampoco hay ventajas específicas para hacerlos no estáticos. Es principalmente 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:
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 haga una diferencia significativa.
fuente
La respuesta correcta es:
cualquier método que no tome ninguna información de un campo, y no ponga ninguna 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.
fuente
Si.
Al mantenerlos como métodos de instancia, te permites proporcionar una implementación diferente más adelante.
Puede sonar tonto (y en realidad lo sería si esos métodos los usa solo 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. quiere romper el código existente.
Entonces crea una subclase y la devuelve en las nuevas versiones, y dado que los métodos se declararon como métodos de instancia, simplemente deja que el polimorfismo haga su trabajo.
Además, podría beneficiarse al 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 lenguaje.
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 "estática vs instancia", toca algunos puntos interesantes en el diseño de API.
fuente
Un problema acerca de 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 simulacros para métodos estáticos y no puede crear una implementación de subclase del método.
fuente
Si el método es básicamente solo una subrutina que nunca usará previsiblemente información de estado, declare estática.
Esto permite que se use en otros métodos estáticos o en la inicialización de clases, es decir:
fuente
La pregunta estática / no estática se reduce a "¿realmente necesitaré usar un objeto de esta clase"?
Entonces, ¿estás pasando el objeto entre diferentes métodos? ¿El objeto contiene información útil fuera del contexto de los métodos estáticos? ¿Hay alguna razón para no definir métodos en ambos sentidos si los usará en ambos sentidos?
Si tiene este dilema, me parece que tiene todos los datos necesarios para el método flotando en su código fuera del objeto. ¿Es esto lo que quieres? ¿Sería más fácil recopilar siempre esos datos en un objeto cada vez? Puede ser ambivalente acerca de comprometerse con un solo modelo. Si puede hacerlo todo de una manera, elija estática o no estática y vaya con ella.
fuente
Mi preferencia en casos como estos es hacer
computeOne
ycomputeMore
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 da, declara eso
computeOne
ycomputeMore
no debería necesitar acceder a las partes internas de la clase, entonces, ¿por qué dar la oportunidad a los encargados de la clase de entrometerse con las partes internas?fuente
Me gustaría aclarar algunas cosas que otros carteles han dicho ya que da 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 ni siquiera puede anular en la subclase, por lo que estático o no estático 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 viene a su pregunta si un método auxiliar privado debe definirse como estático o no estático. Iré con la respuesta de Steve, ya que marcar un método privado estático muestra que este método no tiene estado ya que también sigo esta regla cuando codifico.
fuente
Según la experiencia, afirmaría que tales métodos privados tienden a ser bastante universales y reutilizables.
Creo que lo primero que debe hacer es hacer la pregunta de 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ía este método como estático para algunas clases de utilidades donde alguien espera verificar antes de implementar un nuevo método que haga exactamente lo mismo.
Tales 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 solo en el lugar donde necesita usarlo. Entonces, la centralización de tales métodos es un camino a seguir.
fuente
Más específicamente al ejemplo que has dado, parece que el propósito de la definición de estos métodos es más para la claridad del código cuando lo estás leyendo que para la funcionalidad (que se definen como privado). En ese caso, ir con static realmente no hace nada para usted, ya que el propósito de static es exponer la funcionalidad de la clase.
fuente
Una razón es que, siendo todo lo demás 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 implícita esta referencia.
fuente
Como mucha gente dijo, ¡hazlo como estático ! Aquí está la regla del pulgar que sigo: si cree que el método es solo una función matemática, es decir, no tiene estado, no involucra ninguna variable de instancia (=> no hay 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 la accesibilidad)
fuente
Fuera del tema: mantendría los métodos auxiliares en una utilidad independiente / clase auxiliar con solo métodos estáticos.
El problema con tener métodos auxiliares en el punto de uso (léase 'misma clase') es que alguien más adelante puede elegir publicar sus propios métodos auxiliares no relacionados en el mismo lugar
fuente
La ventaja de los métodos estáticos privados es que pueden reutilizarse más adelante si necesita reinicializar la variable de clase.
fuente
Sin el modificador estático, no puede darse cuenta de que el método no tiene estado sin un análisis adicional que se puede hacer fácilmente cuando (re) escribe el método.
Luego, el modificador "estático" puede darle ideas sobre la 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 a un método miembro.
fuente
Los declararía como estáticos para marcarlos como apátridas.
Java no tiene un mejor mecanismo para operaciones menores que no se exportan, por lo que creo que la estática privada es aceptable.
fuente