Pregunta

Vamos a decir que tengo una clase diseñada para ejecutarse. Tengo varios métodos privados "ayudantes" dentro de la clase que no requieren el acceso a cualquiera de los miembros de la clase, y operan únicamente en sus argumentos, que devuelven resultados.

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 en particular para especificar computeOne y computeMore como métodos estáticos - o cualquier razón particular para no

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

¿Fue útil?

Solución

Yo prefiero este tipo de métodos de ayuda para ser private static; lo que hará más claro para el lector que no van a modificar el estado del objeto. Mi IDE también mostrará las llamadas a métodos estáticos en cursiva, por lo que sabrá el método es estático sin mirar la firma.

Otros consejos

Podría resultar en código de bytes 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 hacer una diferencia global).

Me hacerlos estática, ya que generalmente lo hacen, si es posible. Pero eso es sólo conmigo.


EDIT: Esta respuesta se pone cada vez downvoted, posiblemente debido a la afirmación sin fundamento sobre el tamaño del código de bytes. Así que voy a realizar una prueba de realidad.

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

}

Al invocar el método estático tiene dos códigos de bytes (byteops?):. iconst_0 (para el argumento) y invokestatic
Invocando el método no estático toma de tres: aload_1 (para el objeto TestBytecodeSize, supongo), iconst_0 (para el argumento), y invokespecial. (Tenga en cuenta que si éstos no habían sido los métodos privados, habría sido invokevirtual en lugar de invokespecial; ver JLS §7.7 Métodos Invocación .)

Ahora, como dije, no espero que haya ninguna gran diferencia en el rendimiento entre estos dos, aparte del hecho de que invokestatic requiere una menos código de bytes. invokestatic y invokespecial deben ser ambos ligeramente más rápido que invokevirtual, ya que ambos utilizan enlace estático en lugar de dinámica, pero no tengo ni idea de si bien es más rápido que el otro. No puedo encontrar ningún buenas referencias tampoco. El más cercano que puedo encontrar es este artículo JavaWorld 1997 , que reitera básicamente lo que acabo de decir:

  

Las instrucciones más rápidos muy probablemente serán invokespecial y invokestatic, porque los métodos invocados por estas instrucciones están ligados de forma estática. Cuando la JVM resuelve la referencia simbólica para estas instrucciones y lo sustituye por una referencia directa, que la referencia directa probablemente incluirá un puntero a los códigos de bytes reales.

Sin embargo, muchas cosas han cambiado desde 1997.

Así que en conclusión ... supongo que todavía quedo con lo que he dicho antes. La velocidad no debe ser la razón para elegir una sobre la otra, ya que sería un micro-optimización en el mejor.

Mi preferencia personal sería declarar que estática, ya que es un claro indicador de que están sin estado.

La respuesta es ... depende.

Si es miembro de una variable de instancia específica para el objeto que se está tratando, entonces ¿por qué pasarlo como un parámetro en absoluto?

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 */ } 
}

Una de las razones es posible que desee declarar métodos estáticos de ayuda es si es necesario llamar a ellos en el constructor de la clase "antes" o this 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));
    }
}

Esto es un poco de un ejemplo artificial pero claramente recoverInt no puede ser un método de instancia en este caso.

Realmente no puedo pensar en ventajas claras para el método estático privado. Dicho esto, no hay ventajas específicas a hacerlas no estático tampoco. Es principalmente una cuestión de presentación:. Es posible que desee para que sean estática 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:

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

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

respuesta correcta es:

cualquier método que no tiene ninguna información de un campo, y no pone ninguna información en un campo, no tiene por qué ser un método de instancia. Cualquier método que no utiliza o alterar cualquier campo de su clase o un objeto bien podría ser un método estático.

  

o cualquier otra razón particular no a [declaran como estática]?

Sí.

Al mantener como métodos de instancia, usted se permite proporcionar una implementación diferente en el futuro.

Puede sonar tonto (y de hecho lo que sería si esos métodos se utilizan sólo por usted en un programa de línea de 50), pero en las aplicaciones más grandes, o en las bibliotecas utilizadas por otra persona, puede decidir elegir una mejor aplicación, pero no quieren romper el código existente.

Así se crea una subclase y retorno que en las nuevas versiones, y dado que los métodos fueron declarados como métodos de instancia, que acaba de dejar el polimorfismo haga su trabajo.

Además, usted podría beneficiarse de hacer el constructor privado y proporcionar un método de fábrica estática por la misma razón.

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

Vea aquí para ver un video de alguna manera relacionado: Cómo diseñar una buena API y por qué es importante

A pesar de que no está directamente relacionado con la discusión método de "estática vs instancia", ya que atañe a algunos puntos interesantes en el diseño de la API.

Una cuestión de tener métodos estáticos es que puede hacer que el objeto más difícil de utilizar en las pruebas unidad . Mockito no puede crear burla para los métodos estáticos y no se puede crear una subclase aplicación del método.

Si el método es básicamente una subrutina que nunca va a usar la información de estado previsiblemente, declararlo estática.

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

public class Example {
   //...

   //Only possible if computeOne is static
   public final static double COMPUTED_ONE = computeOne(new Something("1"));

   //...
}

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

En el ejemplo que das, que establecen que computeOne computeMoreand no debería necesitar acceder a las partes internas de la clase, así que ¿por qué dar la oportunidad a los mantenedores de la clase entrometerse en las partes internas.

Me gustaría aclarar algunas cosas, que otros críticos han dicho que su información errónea dando.

En primer lugar ya que los métodos son privadas, incluso si se declara ellas estática que no podrán acceder a ellos fuera de esta clase. En segundo lugar son privadas por lo que ni siquiera se pueden anular en la subclase de manera estática o no estática no hace ninguna diferencia. En tercer lugar un método privado no estático puede ser llamado desde un constructor de la clase también, no tiene por qué ser estática.

Ahora que se acerca a su pregunta si un método de ayuda privado debería definirse como estática o no estático. Voy a ir con la respuesta de Steve como marcar un método privado espectáculos estáticos que este método es sin estado como yo también siguen esta regla cuando código.

A partir de la experiencia, sin afirmar que tales métodos privados tienden a ser bastante universal y reutilizable.

Creo que la primera cosa que hacer es preguntar a la cuestión de si el método puede ser útil fuera del contexto de clase actual. Si es así, lo haría exactamente lo que sugiere Todo el mundo y extraer este método como estática en cierta clase de utilidades en la que alguien con suerte comprobaciones antes de implementar nuevo método de hacer exactamente lo mismo.

Tal uso general métodos privados son fuente de gran parte de la duplicación de código en el proyecto porque cada desarrollador independiente que reinventa justo en el lugar que necesita para usarlo. Así centralización de tales métodos es un camino a seguir.

La cuestión estática / no estática se reduce a "¿Realmente necesita utilizar un objeto de esta clase"?

Entonces, ¿estás pasando el objeto entre los diferentes métodos? ¿Tiene el objeto contiene información que es útil fuera del contexto de los métodos estáticos? ¿Hay alguna razón para no definir métodos en ambos sentidos si se les va a utilizar en ambos sentidos?

Si usted está en este dilema, me parece que tiene todos los datos necesarios para el método flotando alrededor de su código fuera del objeto. ¿Es esto lo que quieres? ¿Sería más fácil para recoger simplemente siempre que los datos en un objeto cada vez? Usted podría ser ambivalente acerca de comprometerse con un único modelo. Si puede hacerlo todo utilizando de una manera, a continuación, elegir ya sea estática o no estático e ir con ella.

Más específicamente al ejemplo que has dado, parece que el propósito de definir estos métodos es más para la claridad del código cuando lo estás leyendo que para la funcionalidad (que son define como privado) . En ese caso, ir con estática en realidad no hace nada para usted, ya que el propósito de la estática es exponer la funcionalidad de clase.

Una de las razones es que, siendo todo lo demás, las llamadas a métodos estáticos iguales deben ser más rápido. Los métodos estáticos no pueden ser virtuales, y no tener una implícita esta referencia.

Off-Topic: Me gustaría mantener los métodos de ayuda en una clase de utilidad / ayudante independiente con sólo métodos estáticos en el mismo.

El problema de tener métodos de ayuda en el punto de uso (leer 'misma clase') es que alguien en la línea sólo puede optar por publicar sus propios métodos de ayuda no relacionados en el mismo lugar

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 se pueden volver a utilizar más adelante si es necesario reinicializar la variable de clase.

  1. Sin el modificador static no puede darse cuenta de que el método no tiene estado sin un análisis adicional que se puede hacer fácilmente cuando se (re) escribir el método.

  2. A continuación modificador "estática" puede darle ideas sobre refactorización además de otras cosas que otras personas encuentren inútil. P.ej. mover el método a alguna clase de utilidad o la conversión a un método miembro ..

Me declararlos como estática para marcarlos como apátridas.

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

Como se ha dicho muchas personas, que es como un estática ! Aquí está la regla del pulgar que sigo: Si piensa que el método es sólo un función matemática es decir, que no tiene estado, no implica ningún variables de instancia (=> no hay VARs color azul [en Eclipse] en el método), y el resultado del método será el mismo para el número 'n' de llamadas (con los mismos parámetros, ofcourse), a continuación, marcar ese método como estática.

Y si usted piensa que este método será útil para otra clase a continuación, pasar a una clase Util lo contrario, poner el método privado en el sameclass. (Minimizando la accesibilidad)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top