Java: quando usare metodi statici


911

Mi chiedo quando utilizzare i metodi statici? Dire se ho una classe con alcuni getter e setter, un metodo o due e voglio che quei metodi siano invocabili solo su un oggetto istanza della classe. Questo significa che dovrei usare un metodo statico?

per esempio

Obj x = new Obj();
x.someMethod

o

Obj.someMethod

(è questo il modo statico?)

Sono piuttosto confuso!

Risposte:


1458

Una regola empirica: chiediti "Ha senso chiamare questo metodo, anche se nessun oggetto è stato ancora costruito?" In tal caso, dovrebbe essere sicuramente statico.

Quindi in una classe Carpotresti avere un metodo:

double convertMpgToKpl(double mpg)

... che sarebbe statico, perché si potrebbe voler sapere in cosa converte 35mpg, anche se nessuno ha mai creato un Car. Ma questo metodo (che imposta l'efficienza di un particolare Car):

void setMileage(double mpg)

... non può essere statico poiché è inconcepibile chiamare il metodo prima che qualcuno Carsia stato costruito.

(A proposito, il contrario non è sempre vero: a volte potresti avere un metodo che coinvolge due Caroggetti e vuoi comunque che sia statico.

Car theMoreEfficientOf( Car c1, Car c2 )

Anche se questo potrebbe essere convertito in una versione non statica, alcuni sosterrebbero che dal momento che non esiste una scelta "privilegiata" che Carè più importante, non dovresti forzare un chiamante a sceglierne uno Carcome l'oggetto che invocherai metodo attivo. Questa situazione rappresenta comunque una piccola parte di tutti i metodi statici.)


325
Alcuni buoni esempi qui. Vorrei aggiungere, tuttavia, che "statico" è spesso utile quando sai che qualcosa non cambierà tra le varie istanze. In tal caso, prenderei davvero in considerazione il "Principio della singola responsabilità", che implica che una classe dovrebbe avere una responsabilità e quindi solo una ragione per cambiare. Penso che si dovrebbe considerare di spostare la funzione "ConvertMpgToKpl (double mpg)" e metodi simili nella propria classe. Lo scopo di un oggetto auto è consentire l'istanza delle auto, non fornire un confronto tra di esse. Quelli dovrebbero essere esterni alla classe.
Zack Jannsen,

34
Penso che preferirei il metodo Car#isMoreEfficientThan(Car). Ha il vantaggio che l'auto che ritorni in pareggio non è arbitraria. È ovvio dal titolo del metodo cosa viene restituito in pareggio.
Cruncher,

5
Vorrei anche fare attenzione a creare un metodo statico che utilizza alcune risorse esterne (filesystem, database, ecc.) Questo tipo di statico può rendere orribile testare i metodi di consumo. Personalmente cerco di mantenere la statica nel regno dell '"utilità".
Seth M.

7
In effetti, dovrebbe essere implementato come comparatore .
Dogweather,

3
@ B1KMusic Certo. Ciò che intendo con "quale auto viene restituita in pareggio" è "mappe vere sull'auto chiamata e mappe false sull'auto passata". È senza ambiguità.
Cruncher,

538

Definire i metodi statici solo nei seguenti scenari:

  1. Se si stanno scrivendo classi di utilità e non si suppone che vengano modificate.
  2. Se il metodo non utilizza alcuna variabile di istanza.
  3. Se qualsiasi operazione non dipende dalla creazione dell'istanza.
  4. Se esiste del codice che può essere facilmente condiviso da tutti i metodi di istanza, estrarre quel codice in un metodo statico.
  5. Se si è certi che la definizione del metodo non verrà mai modificata o ignorata. Poiché i metodi statici non possono essere ignorati.

45
punti positivi, ma sono requisiti se si desidera rendere statico un metodo, non motivi per crearne uno.
tetsuo,

4
@Mohd sul requisito 5: quando puoi essere sicuro al 100% che un metodo non verrà mai modificato o ignorato? Non ci sono sempre fattori sconosciuti che non puoi prendere in considerazione nel momento in cui scrivi il tuo metodo statico?
PixelPlex,

8
Le "Classi di utilità" sono molto difficili da ragionare, la cosa brutta è che prima o poi tutto inizia a "sembrare" un'utilità (sì, mi riferisco a quel pacchetto "util" che è gonfio, intoccabile e scarsamente testato), e i tuoi casi di test avranno bisogno di più lavoro (deridere i programmi di utilità statici è DIFFICILE). Preferisci prima gli oggetti.
Sergio,

2
@Mohd questa risposta è esattamente quello che sto cercando. Ho affrontato molti problemi utilizzando metodi statici nel multithreading. Potete per favore elaborare altri punti 2, 3 (con esempio 100 pollici in su per voi)
Prakash Pandey,

Penso che una "classe statica" dovrebbe essere inventata se si intende utilizzare variabili e metodi statici.
Robert Rocha,

182

Esistono alcuni motivi validi per utilizzare metodi statici:

  • Prestazioni : se si desidera eseguire del codice e non si desidera creare un'istanza di un oggetto aggiuntivo per farlo, inserirlo in un metodo statico. La JVM può anche ottimizzare molto i metodi statici (penso di aver letto una volta James Gosling dichiarando che non hai bisogno di istruzioni personalizzate nella JVM, poiché i metodi statici saranno altrettanto veloci, ma non sono riuscito a trovare l'origine - quindi potrebbe essere completamente falso). Sì, è micro-ottimizzazione e probabilmente non necessaria. E noi programmatori non facciamo mai cose non necessarie solo perché sono belle, giusto?

  • Praticità : anziché chiamare new Util().method(arg), chiamare Util.method(arg)o method(arg)con importazioni statiche. Più facile, più corto.

  • Aggiunta di metodi : volevi davvero che la classe String avesse un removeSpecialChars()metodo di istanza, ma non è presente (e non dovrebbe esserlo, poiché i caratteri speciali del tuo progetto potrebbero essere diversi dagli altri progetti) e non puoi aggiungerlo (dal momento che Java è piuttosto sano), quindi crei una classe di utilità e chiami removeSpecialChars(s)invece di s.removeSpecialChars(). Dolce.

  • Purezza : prendendo alcune precauzioni, il tuo metodo statico sarà una funzione pura , cioè l'unica cosa da cui dipende è i suoi parametri. Dati in entrata, dati in uscita. Questo è più facile da leggere ed eseguire il debug, dal momento che non hai problemi di ereditarietà di cui preoccuparti. Puoi farlo anche con metodi di istanza, ma il compilatore ti aiuterà un po 'di più con metodi statici (non consentendo riferimenti ad attributi di istanza, metodi di sostituzione, ecc.).

Dovrai anche creare un metodo statico se vuoi creare un singleton, ma ... non farlo. Voglio dire, pensaci due volte.

Ora, cosa più importante, perché non vorresti creare un metodo statico? Fondamentalmente, il polimorfismo esce dalla finestra . Non sarai in grado di sovrascrivere il metodo, né dichiararlo in un'interfaccia (pre-Java 8) . Prende molta flessibilità dal tuo design. Inoltre, se hai bisogno di stato , finirai con molti bug di concorrenza e / o colli di bottiglia se non stai attento.


1
Molte buone ragioni elencate qui quando statica può essere utile. Un'altra cosa a cui riesco a pensare è che scrivere unit test per tali metodi è semplicemente semplice
nilesh

@tetsuo Grazie! La tua spiegazione è molto chiara e le ragioni fornite sono molto logiche e hanno molto senso.
Deniss M.

3
E noi programmatori non facciamo mai cose non necessarie solo perché sono belle, giusto? +1
Scaramouche

Detto questo un metodo statico diventa un nome di funzione completa stackoverflow.com/questions/155609/...
Ivanzinho

Sono d'accordo con prestazioni e praticità, ma non con la purezza. Il metodo statico può modificare i membri statici della classe (che possono essere privati). Questo può essere utile Ad esempio, potresti avere un metodo come "static sincronized int allocateID () {return idNext ++;}". In effetti, un metodo statico può essere altrettanto puro o impuro di un metodo non statico in termini di effetti collaterali.
Adam Gawne-Cain,

42

Dopo aver letto gli articoli di Misko, credo che i metodi statici siano cattivi dal punto di vista dei test. Dovresti invece avere fabbriche (magari usando uno strumento di iniezione di dipendenza come Guice ).

come posso assicurarmi di avere solo una cosa?

ho solo uno di qualcosa Il problema di "come posso assicurarmi di avere solo uno di qualcosa" è ben evitato. Istanzia solo una singola ApplicationFactory nel tuo main e, di conseguenza, crei un'istanza di una singola istanza di tutti i tuoi singoli.

Il problema di base con i metodi statici è che sono codici procedurali

Il problema di base con i metodi statici è che sono codici procedurali. Non ho idea di come testare il codice procedurale. Il test unitario presuppone che posso istanziare una parte della mia applicazione in modo isolato. Durante l'istanza collego le dipendenze con derisioni / amichevoli che sostituiscono le dipendenze reali. Con la programmazione procedurale non c'è nulla da "cablare" poiché non ci sono oggetti, il codice e i dati sono separati.


20
Non capisco la parte sul non essere in grado di testare il codice procedurale. Non impostare semplicemente casi di test che associano l'input corretto all'output corretto usando il metodo statico insieme alla classe come "unità"?
martedì

2
Potresti farlo per testare quelle funzioni. Ma quando si utilizzano questi metodi statici in altre classi che si desidera testare, credo che non si possano falsificare (beffe / amichevoli) o altro, perché non è possibile creare un'istanza di una classe.
Alfred

4
@Alfred: dai un'occhiata a PowerMock che ha la capacità di deridere i metodi statici. Utilizzando PowerMock ci sono alcuni scenari, se presenti, in cui si trovano dipendenze del metodo che non possono essere derise.
Carles Sala,

7
Puoi testare le statistiche dei test unitari usando PowerMock, tuttavia ti accorgerai presto di esaurire lo spazio di Permgen (fatto, hai la maglietta), ed è ancora brutto. A meno che tu NON SO (basato su almeno un decennio della tua esperienza nelle lingue OO reali, non migrando da C), allora NON FARLO. Scherzi a parte, il peggior codice che abbia mai visto è venuto dall'uso di statica da parte di uno sviluppatore incorporato e nella maggior parte dei casi ne siamo rimasti bloccati, per sempre, e l'aggiunta di altro codice ci ha bloccato nel monolito immodificabile ancora più strettamente. Accoppiamento libero: no, testabile: a malapena, modificabile: MAI. Evitare!
user1016765,

14
Riesco a capire la difficoltà di testare metodi statici che dipendono dallo stato statico. Ma quando stai testando metodi statici senza stato come Math.abs()o Arrays.sort(), anche metodi in cui puoi passare tutte le dipendenze , non vedo come ciò possa impedire il test unitario. Direi che una semplice regola empirica è: se mai avessi qualche motivo per deridere la logica procedurale, allora non metterla in un metodo statico. Non ho mai avuto motivo di deridere Arrays.sort()o Math.abs().
Andy

36

Un staticmetodo è un tipo di metodo che non ha bisogno di inizializzare alcun oggetto per essere chiamato. Hai notato che staticviene utilizzato nella mainfunzione in Java? L'esecuzione del programma inizia da lì senza la creazione di un oggetto.

Considera il seguente esempio:

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

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }

migliore risposta in realtà
Yahya,

20

I metodi statici in Java appartengono alla classe (non un'istanza di essa). Non usano variabili di istanza e di solito accettano input dai parametri, eseguono azioni su di esso, quindi restituiscono alcuni risultati. I metodi delle istanze sono associati agli oggetti e, come suggerisce il nome, possono utilizzare le variabili di istanza.


12

No, i metodi statici non sono associati a un'istanza; appartengono alla classe. I metodi statici sono il tuo secondo esempio; i metodi di istanza sono i primi.


1
Dovresti usare metodi statici se non hai bisogno di manipolazioni dello stato dell'oggetto.
MastAvalons,

11

Se si applica una parola chiave statica con qualsiasi metodo, è noto come metodo statico.

  1. Un metodo statico appartiene alla classe anziché all'oggetto di una classe.
  2. Un metodo statico richiamato senza la necessità di creare un'istanza di una classe.
  3. Il metodo statico può accedere al membro di dati statici e può modificarne il valore.
  4. È possibile accedere a un metodo statico semplicemente utilizzando il nome di un nome statico punto dot. . . esempio: Student9.change ();
  5. Se si desidera utilizzare campi non statici di una classe, è necessario utilizzare un metodo non statico.

// Programma di modifica della proprietà comune di tutti gli oggetti (campo statico).

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 indiano 222 BBDIT americano 333 BBDIT Cina


10

I metodi statici non sono associati a un'istanza, quindi non possono accedere ad alcun campo non statico nella classe.

Si utilizzerà un metodo statico se il metodo non utilizza alcun campo (o solo campi statici) di una classe.

Se vengono utilizzati campi non statici di una classe, è necessario utilizzare un metodo non statico.


1
Risposta chiara, breve e semplice.
Josi,

8

I metodi statici dovrebbero essere chiamati sulla Classe, i metodi di Istanza dovrebbero essere chiamati sulle Istanze della Classe. Ma cosa significa in realtà? Ecco un esempio utile:

Una classe di auto potrebbe avere un metodo di istanza chiamato Accelerate (). Puoi solo accelerare un'auto, se l'auto esiste effettivamente (è stata costruita) e quindi questo sarebbe un metodo di istanza.

Una classe di auto potrebbe anche avere un metodo di conteggio chiamato GetCarCount (). Ciò restituirebbe il numero totale di auto create (o costruite). Se non fosse stata costruita alcuna macchina, questo metodo restituirebbe 0, ma dovrebbe comunque essere possibile chiamarlo e quindi dovrebbe essere un metodo statico.


6

In realtà, usiamo proprietà e metodi statici in una classe, quando vogliamo usare una parte del nostro programma dovrebbe esistere lì fino a quando il nostro programma è in esecuzione. E sappiamo che, per manipolare le proprietà statiche, abbiamo bisogno di metodi statici in quanto non fanno parte della variabile di istanza. E senza metodi statici, manipolare le proprietà statiche richiede tempo.


Mantenere lo stato nelle variabili statiche è una brutta cosa da fare per molte ragioni - come la sicurezza multi-thread, il debug, l'incapsulamento dei dati ... ecc. I metodi statici sono OK se sono funzioni pure (funzionano solo con i parametri, senza cambiarle). Un buon esempio potrebbe essere una classe di utilità, per esempio calcoli matematici.
Vladimir Demirev,

5

Utilizzare un metodo statico quando si desidera poter accedere al metodo senza un'istanza della classe.


29
Ciò non fornisce alcuna motivazione per la progettazione di un programma.
adamjmarkham,

4

Statico: Obj.someMethod

Utilizzare staticquando si desidera fornire l'accesso a livello di classe a un metodo, ovvero dove il metodo deve essere richiamabile senza un'istanza della classe.


4

Non è necessario invocare metodi statici sull'oggetto, ovvero quando lo si utilizza. Esempio: il tuo Main () è statico e non crei un oggetto per chiamarlo.


1
Sìì! Guarda dove sono arrivato mentre cercavo su Google domande su Noobie Java! È un piccolo mondo :-)
Deepak il

1
@Deepak piccolo mondo davvero :)
Vaishak Suresh

4

I metodi e le variabili statici sono la versione controllata delle funzioni e delle variabili "globali" in Java. In quali metodi è possibile accedere come classname.methodName()o classInstanceName.methodName(), ovvero è possibile accedere a metodi e variabili statici utilizzando il nome della classe e le istanze della classe.

La classe non può essere dichiarata come statica (perché non ha senso. Se una classe viene dichiarata pubblica, è possibile accedervi da qualsiasi luogo), le classi interne possono essere dichiarate statiche.


3

I metodi statici possono essere usati se

  • Non si desidera eseguire un'azione su un'istanza (metodi di utilità)

    Come menzionato in alcune delle risposte precedenti in questo post, convertendo miglia in chilometri o calcolando la temperatura da Fahrenheit a Celsius e viceversa. Con questi esempi che utilizzano il metodo statico, non è necessario creare un'istanza di un oggetto completamente nuovo nella memoria dell'heap. Considerare di seguito

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

    il primo crea un nuovo footprint di classe per ogni metodo invocare, Performance, Pratico . Esempi sono la libreria StringUtils di Math e Apache-Commons di seguito:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
  • Uno vuole usare come una semplice funzione. Gli input vengono esplicitamente passati e ottengono i dati dei risultati come valore di ritorno. Eredità, istanciazione dell'oggetto non appare in figura. Conciso, leggibile .

NOTA : Poche persone discutono contro la testabilità dei metodi statici, ma anche i metodi statici possono essere testati! Con jMockit, si possono deridere metodi statici. Testabilità . Esempio sotto:

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

3

I metodi statici sono i metodi in Java che possono essere chiamati senza creare un oggetto di classe. Appartiene alla classe.

Usiamo il metodo statico quando non è necessario invocare il metodo usando l'istanza.


2

Mi chiedo quando utilizzare i metodi statici?

  1. Un uso comune dei staticmetodi è l'accesso ai staticcampi.
  2. Ma puoi avere staticmetodi, senza fare riferimento alle staticvariabili. I metodi di supporto senza staticvariabile di riferimento possono essere trovati in alcune classi java come java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. L'altro caso d'uso, posso pensare a questi metodi combinati con il synchronizedmetodo è l'implementazione del blocco a livello di classe in un ambiente multi-thread.

Dire se ho una classe con alcuni getter e setter, un metodo o due e voglio che quei metodi siano invocabili solo su un oggetto istanza della classe. Questo significa che dovrei usare un metodo statico?

Se è necessario accedere al metodo su un oggetto istanza della classe, il metodo deve essere non statico.

La pagina della documentazione di Oracle fornisce ulteriori dettagli.

Non sono consentite tutte le combinazioni di variabili e metodi di istanza e classe:

  1. I metodi di istanza possono accedere direttamente alle variabili di istanza e ai metodi di istanza.
  2. I metodi di istanza possono accedere direttamente alle variabili di classe e ai metodi di classe.
  3. I metodi di classe possono accedere direttamente alle variabili di classe e ai metodi di classe.
  4. I metodi di classe non possono accedere direttamente alle variabili di istanza o ai metodi di istanza, ma devono utilizzare un riferimento ad oggetto. Inoltre, i metodi di classe non possono utilizzare questa parola chiave in quanto non esiste un'istanza a cui fare riferimento.

Non possiamo accedere ai campi statici con metodi regolari? Quindi questo A common use for static methods is to access static fields.non è un argomento.
parsecer

2

Un metodo statico ha due scopi principali:

  1. Per metodi di utilità o di aiuto che non richiedono alcuno stato oggetto. Poiché non è necessario accedere alle variabili di istanza, la presenza di metodi statici elimina la necessità per il chiamante di creare un'istanza dell'oggetto solo per chiamare il metodo.
  2. Per lo stato condiviso da tutte le istanze della classe, come un contatore. Tutte le istanze devono condividere lo stesso stato. Anche i metodi che usano semplicemente quello stato dovrebbero essere statici.

1

In eclipse puoi abilitare un avviso che ti aiuta a rilevare potenziali metodi statici. (Sopra la linea evidenziata ce n'è un'altra che ho dimenticato di evidenziare)

impostazione eclissi


0

Ogni volta che non si desidera creare un oggetto per chiamare un metodo nel proprio codice, dichiararlo come statico. Dal momento che il metodo statico non ha bisogno di un'istanza da chiamare ma il fermo qui non è che tutti i metodi statici vengano chiamati automaticamente da JVM. Questo privilegio è goduto solo dal metodo main () "public static void main [String ... args]" in java perché in Runtime questo è il metodo Signature public "static" void main [] cercato da JVM come punto di accesso a avviare l'esecuzione del codice.

Esempio:

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");
   }
} 

Output: - Questo metodo statico viene eseguito da JVM Questo metodo statico deve essere chiamato esplicitamente Questo metodo statico deve essere chiamato esplicitamente Questo metodo statico deve essere chiamato esplicitamente

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.