Java: cuándo usar métodos estáticos

911

Me pregunto cuándo usar métodos estáticos. Digamos si tengo una clase con algunos captadores y establecedores, un método o dos, y quiero que esos métodos solo sean invocables en un objeto de instancia de la clase. ¿Esto significa que debería usar un método estático?

p.ej

Obj x = new Obj();
x.someMethod

o

Obj.someMethod

(¿Es esta la forma estática?)

Estoy bastante confundido!

KP65
fuente

Respuestas:

1458

Una regla general: pregúntese "¿Tiene sentido llamar a este método, incluso si todavía no se ha construido ningún objeto?" Si es así, definitivamente debería ser estático.

Entonces, en una clase Car, podrías tener un método:

double convertMpgToKpl(double mpg)

... lo cual sería estático, porque uno podría querer saber a qué se convierte 35mpg, incluso si nadie ha construido alguna vez un Car. Pero este método (que establece la eficiencia de un particular Car):

void setMileage(double mpg)

... no puede ser estático ya que es inconcebible llamar al método antes de que Carse haya construido ninguno .

(Por cierto, lo contrario no siempre es cierto: a veces puede tener un método que involucra dos Carobjetos, y aún así quiere que sea estático. Por ejemplo:

Car theMoreEfficientOf( Car c1, Car c2 )

Aunque esto podría convertirse a una versión no estática, algunos argumentarían que, dado que no existe una opción "privilegiada", lo cual Cares más importante, no debe obligar a la persona que llama a elegir una Carcomo el objeto que invocará. método en. Sin embargo, esta situación representa una fracción bastante pequeña de todos los métodos estáticos).

no solo yeti
fuente
325
Algunos buenos ejemplos aquí. Sin embargo, agregaría que "estático" a menudo es valioso cuando se sabe que algo no va a cambiar en todas las instancias. Si este es el caso, realmente consideraría el "Principio de responsabilidad única", que implica que una clase debe tener una responsabilidad y, por lo tanto, solo una razón para cambiar. Creo que uno debería considerar mover la función "ConvertMpgToKpl (doble mpg)", y métodos similares, a su propia clase. El propósito de un objeto de automóvil es permitir la creación de instancias de automóviles, no proporcionar una comparación entre ellos. Esos deben ser externos a la clase.
Zack Jannsen el
34
Creo que preferiría el método Car#isMoreEfficientThan(Car). Tiene la ventaja de que el auto que devuelve en un empate no es arbitrario. Es obvio por el título del método lo que se devuelve en un empate.
Cruncher
55
También sería cuidadoso al crear un método estático que utilice algún recurso externo (sistema de archivos, base de datos, etc.), este tipo de estática puede hacer que sea horrible probar los métodos de consumo. Personalmente trato de mantener la estática en el ámbito de la "utilidad".
Seth M.
77
De hecho, debe implementarse como un comparador .
Dogweather
3
@ B1KMusic Por supuesto. Lo que quiero decir con "qué auto se devuelve en un empate" es "mapas verdaderos para el auto llamado y mapas falsos para el auto pasado". Es sin ambigüedad.
Cruncher
538

Defina métodos estáticos solo en los siguientes escenarios:

  1. Si está escribiendo clases de utilidad y se supone que no deben cambiarse.
  2. Si el método no usa ninguna variable de instancia.
  3. Si alguna operación no depende de la creación de la instancia.
  4. Si hay algún código que pueda ser compartido fácilmente por todos los métodos de instancia, extraiga ese código en un método estático.
  5. Si está seguro de que la definición del método nunca se cambiará ni se anulará. Como los métodos estáticos no se pueden anular.
Mohd
fuente
46
puntos buenos, pero son requisitos si desea que un método sea estático, no razones para hacerlo.
tetsuo
44
@Mohd sobre el requisito 5: ¿Cuándo puede estar 100% seguro de que un método nunca se cambiará o se anulará? ¿No siempre hay factores desconocidos que no puedes tener en cuenta en el momento en que escribes tu método estático?
PixelPlex
8
Las "clases de utilidad" son muy difíciles de razonar, lo malo es que tarde o temprano todo comienza a "parecerse" a una utilidad (sí, me refiero a ese paquete de "utilidad" que está hinchado, intocable y mal probado), y sus casos de prueba necesitarán más trabajo (burlarse de las utilidades estáticas es DURO). Prefiere los objetos primero.
Sergio
2
@Mohd esta respuesta es exactamente lo que estoy buscando. Me enfrenté a muchos problemas al usar métodos estáticos en subprocesos múltiples. ¿Puede por favor elaborar puntos 2, 3 más (con el ejemplo 100 aprobado por usted)
Prakash Pandey
Creo que se debe inventar una "clase estática" si va a utilizar variables y métodos estáticos.
Robert Rocha
182

Hay algunas razones válidas para usar métodos estáticos:

  • Rendimiento : si desea ejecutar algún código y no desea crear una instancia de un objeto adicional para hacerlo, introdúzcalo en un método estático. La JVM también puede optimizar mucho los métodos estáticos (creo que una vez leí a James Gosling declarando que no necesita instrucciones personalizadas en la JVM, ya que los métodos estáticos serán igual de rápidos, pero no pudieron encontrar la fuente, por lo tanto podría ser completamente falso). Sí, es micro-optimización, y probablemente innecesaria. Y nosotros los programadores nunca hacemos cosas innecesarias solo porque son geniales, ¿verdad?

  • Practicidad : en lugar de llamar new Util().method(arg), llamar Util.method(arg)o method(arg)con importaciones estáticas. Más fácil, más corto.

  • Agregar métodos : realmente quería que la clase String tuviera un removeSpecialChars()método de instancia, pero no está allí (y no debería, ya que los caracteres especiales de su proyecto pueden ser diferentes de los del otro proyecto), y no puede agregarlo (ya que Java es algo sensato), por lo que crea una clase de utilidad y llama en removeSpecialChars(s)lugar de s.removeSpecialChars(). Dulce.

  • Pureza : tomando algunas precauciones, su método estático será una función pura , es decir, lo único de lo que depende es de sus parámetros. Datos de entrada, datos de salida. Esto es más fácil de leer y depurar, ya que no tiene que preocuparse por las peculiaridades de la herencia. También puede hacerlo con métodos de instancia, pero el compilador lo ayudará un poco más con los métodos estáticos (al no permitir referencias a atributos de instancia, métodos de anulación, etc.).

También tendrá que crear un método estático si desea hacer un singleton, pero ... no lo haga. Quiero decir, piénsalo dos veces.

Ahora, más importante, ¿por qué no querrías crear un método estático? Básicamente, el polimorfismo sale por la ventana . No podrá anular el método ni declararlo en una interfaz (anterior a Java 8) . Se necesita mucha flexibilidad de su diseño. Además, si necesita estado , terminará con muchos errores de concurrencia y / o cuellos de botella si no tiene cuidado.

tetsuo
fuente
1
Muchas de las buenas razones enumeradas aquí cuando estática puede ser útil. Otra cosa que se me ocurre es que escribir pruebas unitarias para tales métodos es simplemente simple
nilesh
@tetsuo Gracias! Su explicación es muy clara y las razones proporcionadas son muy lógicas y tienen mucho sentido.
Deniss M.
3
Y nosotros los programadores nunca hacemos cosas innecesarias solo porque son geniales, ¿verdad? +1
Scaramouche
Dicho esto, un método estático se convierte en una función con nombre completo stackoverflow.com/questions/155609/…
Ivanzinho
Estoy de acuerdo con el rendimiento y la practicidad, pero no con la pureza. El método estático puede modificar miembros estáticos de la clase (que pueden ser privados). Esto puede ser útil. Por ejemplo, podría tener un método como "estático sincronizado int allocateID () {return idNext ++;}". De hecho, un método estático puede ser tan puro o impuro como un método no estático en términos de efectos secundarios.
Adam Gawne-Cain
42

Después de leer los artículos de Misko, creo que los métodos estáticos son malos desde el punto de vista de la prueba. Debería tener fábricas en su lugar (tal vez utilizando una herramienta de inyección de dependencia como Guice ).

¿Cómo me aseguro de tener solo uno de algo?

solo tengo uno de algo El problema de "¿cómo me aseguro de que solo tengo uno de algo" está muy bien evitado. Solo crea una instancia de ApplicationFactory en su main y, como resultado, solo crea una instancia de todos sus singletons.

El problema básico con los métodos estáticos es que son código de procedimiento

El problema básico con los métodos estáticos es que son código de procedimiento. No tengo idea de cómo probar el código de procedimiento de la unidad. Las pruebas unitarias suponen que puedo crear una instancia de una parte de mi aplicación de forma aislada. Durante la instanciación, conecto las dependencias con simulacros / amistosos que reemplazan las dependencias reales. Con la programación de procedimientos no hay nada que "conectar" ya que no hay objetos, el código y los datos están separados.

Alfredo
fuente
20
No entiendo la parte de no poder probar el código de procedimiento de la unidad. ¿No acabas de configurar casos de prueba que mapean la entrada correcta a la salida correcta usando el método estático junto con la clase como tu "unidad"?
tjb
2
Podrías hacer eso para probar esas funciones. Pero cuando usa estos métodos estáticos en otras clases que desea probar, creo que no puede falsificarlos (simulacros / amistosos) ni nada, porque no puede crear una instancia de una clase.
Alfred
44
@Alfred: Eche un vistazo a PowerMock que tiene la capacidad de burlarse de los métodos estáticos. Usando PowerMock, hay algunos escenarios, si los hay, en los que encuentra dependencias de métodos que no se pueden burlar.
Carles Sala
77
Puedes probar las unidades estáticas usando PowerMock, sin embargo, pronto encontrarás que te quedas sin espacio en Permgen (hecho eso, obtuve la camiseta), y todavía es desagradable. A menos que sepa (basado en al menos una década de su propia experiencia en verdaderos lenguajes OO, sin migrar desde C), NO LO HAGA. En serio, el peor código que he visto proviene del uso de estática de un desarrollador incrustado y, en la mayoría de los casos, nos quedamos atrapados con él, para siempre, y agregar más código nos encerró aún más en el monolito inmodificable. Acoplamiento suelto: no, comprobable: apenas, modificable: NUNCA. ¡Evitar!
user1016765
14
Puedo entender la dificultad de probar métodos estáticos que dependen del estado estático. Pero cuando está probando métodos estáticos sin estado como Math.abs()o Arrays.sort(), incluso métodos en los que puede pasar todas las dependencias , no veo cómo eso impediría alguna vez las pruebas unitarias. Diría que una regla general simple es: si alguna vez tiene alguna razón para burlarse de la lógica de procedimiento, entonces no la ponga en un método estático. Nunca he tenido una razón para burlarme Arrays.sort()o Math.abs().
Andy
36

Un staticmétodo es un tipo de método que no necesita ningún objeto para inicializarse para que se llame. ¿Has notado que staticse usa en la mainfunción en Java? La ejecución del programa comienza desde allí sin que se cree un objeto.

Considere el siguiente ejemplo:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }
Zishan
fuente
mejor respuesta en realidad
Yahya
20

Los métodos estáticos en Java pertenecen a la clase (no una instancia de ella). No utilizan variables de instancia y, por lo general, toman datos de los parámetros, realizan acciones en ellos y luego devuelven algún resultado. Los métodos de instancias están asociados con objetos y, como su nombre lo indica, pueden usar variables de instancia.

Kevin Sylvestre
fuente
12

No, los métodos estáticos no están asociados con una instancia; Pertenecen a la clase. Los métodos estáticos son su segundo ejemplo; Los métodos de instancia son los primeros.

duffymo
fuente
1
Debe usar métodos estáticos si no necesita manipulaciones de estado del objeto.
MastAvalons
11

Si aplica una palabra clave estática con cualquier método, se conoce como método estático.

  1. Un método estático pertenece a la clase en lugar del objeto de una clase.
  2. Un método estático invocado sin la necesidad de crear una instancia de una clase.
  3. El método estático puede acceder al miembro de datos estáticos y puede cambiar su valor.
  4. Se puede acceder a un método estático simplemente usando el nombre de un nombre estático de punto de clase. . . ejemplo: Student9.change ();
  5. Si desea usar campos no estáticos de una clase, debe usar un método no estático.

// Programa para cambiar la propiedad común de todos los objetos (campo estático).

class Student9{  
 int rollno;  
 String name;  
 static String college = "ITS";  

 static void change(){  
 college = "BBDIT";  
 }  

 Student9(int r, String n){  
 rollno = r;  
 name = n;  
 }  

 void display (){System.out.println(rollno+" "+name+" "+college);}  

public static void main(String args[]){  
Student9.change();  

Student9 s1 = new Student9 (111,"Indian");  
Student9 s2 = new Student9 (222,"American");  
Student9 s3 = new Student9 (333,"China");  

s1.display();  
s2.display();  
s3.display();  
}  }

O / P: 111 BBDIT indio 222 BBDIT estadounidense 333 BBDIT de China

Programador indio1234
fuente
10

Los métodos estáticos no están asociados con una instancia, por lo que no pueden acceder a ningún campo no estático en la clase.

Usaría un método estático si el método no usa ningún campo (o solo campos estáticos) de una clase.

Si se usan campos no estáticos de una clase, debe usar un método no estático.

Carsten
fuente
1
Respuesta clara, corta y simple.
Josi
8

Los métodos estáticos deben llamarse en la Clase, los métodos de Instancia deben llamarse en las Instancias de la Clase. Pero, ¿qué significa eso en realidad? Aquí hay un ejemplo útil:

Una clase de automóvil podría tener un método de instancia llamado Accelerate (). Solo puede acelerar un automóvil, si el automóvil realmente existe (ha sido construido) y, por lo tanto, este sería un método de instancia.

Una clase de automóvil también podría tener un método de conteo llamado GetCarCount (). Esto devolvería el número total de automóviles creados (o construidos). Si no se han construido automóviles, este método devolvería 0, pero aún debería poder llamarse y, por lo tanto, debería ser un método estático.

Charlie Seligman
fuente
6

En realidad, usamos propiedades y métodos estáticos en una clase, cuando queremos usar alguna parte de nuestro programa debería existir allí hasta que nuestro programa se esté ejecutando. Y sabemos que, para manipular propiedades estáticas, necesitamos métodos estáticos, ya que no son parte de la variable de instancia. Y sin métodos estáticos, manipular propiedades estáticas lleva mucho tiempo.

Sagar
fuente
Mantener el estado en variables estáticas es algo malo por muchas razones, como la seguridad de múltiples subprocesos, la depuración, la encapsulación de datos, etc., etc. Los métodos estáticos están bien si son funciones puras (solo funcionan con parámetros, sin cambiarlos). Un buen ejemplo sería una clase de utilidad, por ejemplo, cálculos matemáticos.
Vladimir Demirev, el
5

Use un método estático cuando desee poder acceder al método sin una instancia de la clase.

Jamey
fuente
29
Esto no da ninguna justificación para el diseño de un programa.
adamjmarkham el
4

Estático: Obj.someMethod

Úselo staticcuando desee proporcionar acceso a nivel de clase a un método, es decir, donde el método debe ser invocable sin una instancia de la clase.

Finbarr
fuente
4

Los métodos estáticos no necesitan ser invocados en el objeto y eso es cuando lo usa. Ejemplo: su Main () es estático y no crea un objeto para llamarlo.

Vaishak Suresh
fuente
1
¡Hurra! ¡Mira a dónde vine mientras busco en Google preguntas novatas de Java! Es un mundo pequeño :-)
Deepak
1
@Deepak pequeño mundo de hecho :)
Vaishak Suresh
4

Los métodos y variables estáticas son versiones controladas de funciones y variables 'globales' en Java. En qué métodos se puede acceder como classname.methodName()o classInstanceName.methodName(), es decir, se puede acceder a métodos estáticos y variables utilizando el nombre de la clase, así como instancias de la clase.

La clase no se puede declarar como estática (porque no tiene sentido. Si una clase se declara pública, se puede acceder desde cualquier lugar), las clases internas se pueden declarar estáticas.

Manju Yadav
fuente
3

Se pueden usar métodos estáticos si

  • Uno no quiere realizar una acción en una instancia (métodos de utilidad)

    Como se mencionó en algunas de las respuestas anteriores en esta publicación, convertir millas a kilómetros o calcular la temperatura de Fahrenheit a Celsius y viceversa. Con estos ejemplos utilizando el método estático, no es necesario crear instancias de objetos completamente nuevos en la memoria de almacenamiento dinámico. Considere a continuación

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 
    2. ABCClass.convertFarenheitToCelcium(double farenheit)

    el primero crea una nueva huella de clase para cada invocación de método, Rendimiento, Práctico . Los ejemplos son la clase StringUtils de la biblioteca Math y Apache-Commons a continuación:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
  • Uno quiere usarlo como una función simple. Las entradas se pasan explícitamente y se obtienen los datos del resultado como valor de retorno. Herencia, la instanciación de objetos no entra en escena. Conciso, legible .

NOTA : Pocas personas argumentan en contra de la capacidad de prueba de los métodos estáticos, ¡pero los métodos estáticos también se pueden probar! Con jMockit, uno puede burlarse de los métodos estáticos. La capacidad de prueba . Ejemplo a continuación:

new MockUp<ClassName>() {
    @Mock
    public int doSomething(Input input1, Input input2){
        return returnValue;
    }
};
Amit Kaneria
fuente
3

Los métodos estáticos son los métodos en Java que se pueden invocar sin crear un objeto de clase. Es pertenecer a la clase.

Usamos el método estático cuando no necesitamos que se invoque el método usando la instancia.

rashedcs
fuente
2

Me pregunto cuándo usar métodos estáticos.

  1. Un uso común de los staticmétodos es acceder a los staticcampos.
  2. Pero puede tener staticmétodos, sin hacer referencia a staticvariables. Los métodos auxiliares sin staticvariable de referencia se pueden encontrar en algunas clases de java como java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. El otro caso de uso, puedo pensar en estos métodos combinados con el synchronizedmétodo es la implementación del bloqueo de nivel de clase en un entorno de subprocesos múltiples.

Digamos si tengo una clase con algunos captadores y establecedores, un método o dos, y quiero que esos métodos solo sean invocables en un objeto de instancia de la clase. ¿Esto significa que debería usar un método estático?

Si necesita acceder al método en un objeto de instancia de la clase, su método debe ser no estático.

La página de documentación de Oracle proporciona más detalles.

No se permiten todas las combinaciones de variables y métodos de instancia y clase:

  1. Los métodos de instancia pueden acceder a variables de instancia y métodos de instancia directamente.
  2. Los métodos de instancia pueden acceder a variables de clase y métodos de clase directamente.
  3. Los métodos de clase pueden acceder a variables de clase y métodos de clase directamente.
  4. Los métodos de clase no pueden acceder a variables de instancia o métodos de instancia directamente; deben usar una referencia de objeto. Además, los métodos de clase no pueden usar esta palabra clave ya que no hay ninguna instancia a la que se refiera esto.
Ravindra babu
fuente
¿No podemos acceder a los campos estáticos a través de métodos regulares? Entonces esto A common use for static methods is to access static fields.no es un argumento.
analista el
2

Un método estático tiene dos propósitos principales:

  1. Para métodos de utilidad o de ayuda que no requieren ningún estado de objeto. Como no hay necesidad de acceder a las variables de instancia, tener métodos estáticos elimina la necesidad de que la persona que llama cree una instancia del objeto solo para llamar al método.
  2. Para el estado que comparten todas las instancias de la clase, como un contador. Toda instancia debe compartir el mismo estado. Los métodos que simplemente usan ese estado también deberían ser estáticos.
hemanto
fuente
1

En eclipse puede habilitar una advertencia que lo ayuda a detectar posibles métodos estáticos. (Sobre la línea resaltada hay otra que olvidé resaltar)

ajuste de eclipse

ave4496
fuente
0

Siempre que no desee crear un objeto para llamar a un método en su código, simplemente declare ese método como estático. Dado que el método estático no necesita una instancia para ser llamado, pero la captura aquí no es que todos los métodos estáticos sean llamados automáticamente por JVM. Este privilegio es disfrutado solo por el método main () "public static void main [String ... args]" en java porque en Runtime este es el método Signature public "static" void main [] buscado por JVM como punto de entrada a iniciar la ejecución del código.

Ejemplo:

public class Demo
{
   public static void main(String... args) 
   {
      Demo d = new Demo();

      System.out.println("This static method is executed by JVM");

     //Now to call the static method Displ() you can use the below methods:
           Displ(); //By method name itself    
      Demo.Displ(); //By using class name//Recommended
         d.Displ(); //By using instance //Not recommended
   }

   public static void Displ()
   {
      System.out.println("This static method needs to be called explicitly");
   }
} 

Salida: - JVM ejecuta este método estático. Este método estático debe llamarse explícitamente. Este método estático debe llamarse explícitamente. Este método estático debe llamarse explícitamente.

Amrit
fuente