Perché non sei in grado di dichiarare una classe come statica in Java?


459

Perché non sei in grado di dichiarare una classe come statica in Java?


72
Contro-domanda: quale ti aspetteresti l'effetto, se dichiarassi di essere una classe di livello superiore static?
Joachim Sauer,

3
No, non puoi, tranne che per le classi interne statiche. Ma cosa vuoi ottenere con quello?
Manolowar,

60
@Joachim Sauer: Beh, C # interpreta le staticclassi come abstract final, cioè, non possono essere istanziate e non possono essere estese. Ciò significa che possono contenere solo membri statici, utile per le classi che contengono solo metodi di supporto.
Bcat,

30
@bcat questo è vero per C #, ma una classe java può essere astratta o finale, non entrambe. Per impedire che una classe venga istanziata, si può dichiarare un costruttore privato.
Lorenzo Polidori,

7
@JoachimSauer Semplice, mi piacerebbe forzare tutti i membri della classe a essere statici (magari anche con una dichiarazione su ogni metodo o proprietà).
hmartinezd,

Risposte:


475

Solo le classi nidificate possono essere statiche. In questo modo è possibile utilizzare la classe nidificata senza avere un'istanza della classe esterna.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}

Fonti:

Sullo stesso argomento:


3
+1 nonostante la prima frase non sia esatta. Come afferma il tutorial "Le classi nidificate non statiche sono chiamate classi interne". (JLS: "Una classe interna è una classe nidificata che non è dichiarata in modo esplicito o implicito statico.")
user85421

74
Sicuramente hai ragione; ma non vedo come questo risponda alla domanda
Joeri Hendrickx,

2
@Carlos Heuberger, hai ragione, ho aggiornato il post. @Joeri Hendrickx, La domanda era: "perché una classe non può essere dichiarata come statica ..?", Possono e [leggi il mio post qui]. È una spiegazione sull'uso delle classi statiche e perché devono essere classi nidificate.
Colin Hebert,

1
La soluzione fornita qui va bene ... Ma mi chiedo ancora che ppl non abbia spiegato logicamente che la classe statica non è possibile in java ... alcuni OOP spiegazione del concetto sarebbe la risposta giusta. Lo
aspetto

9
È vero, ma la domanda a cui stai pensando di solito si risolve da sola quando inizi a chiederti quale sarebbe una "classe statica". In java, un elemento statico significa che è possibile accedervi / invocarlo senza un'istanza della classe che lo racchiude; cosa potrebbe significare se si applica la parola chiave alla classe stessa? Quali sono le tue intenzioni? Cosa ti aspetteresti? Ora che hai un'idea di cosa potrebbe essere, sono abbastanza sicuro che sarà "non ha davvero senso" o sarà "inverosimile" (avrebbe senso, ma alla fine è solo una scelta che è stato fatto).
Colin Hebert,

39

Le classi di livello superiore sono statiche per impostazione predefinita. Le classi interne sono non statiche per impostazione predefinita. È possibile modificare il valore predefinito per le classi interne contrassegnandole esplicitamente statiche. Le classi di livello superiore, in virtù del fatto che sono di livello superiore, non possono avere semantiche non statiche perché non può esserci alcuna classe genitore a cui fare riferimento. Pertanto, non è possibile modificare l'impostazione predefinita per le classi di livello superiore.


14
»Le classi di livello superiore sono statiche per impostazione predefinita.« Questa è la risposta migliore. Sono statici perché non è necessaria alcuna istanza di nulla per fare riferimento a loro. Possono essere indicati da qualsiasi luogo. Sono in memoria statica (come nelle classi di memoria C). - Come altri hanno notato (Iain Elder in un commento a un'altra risposta), i progettisti del linguaggio avrebbero potuto consentire alla staticparola chiave di una classe di livello superiore di indicare e imporre che potesse contenere solo membri statici e non essere istanziato; ciò, tuttavia, potrebbe aver confuso le persone in quanto staticha un significato diverso per le classi nidificate.
Lumi,

35

Quindi, arrivo tardi alla festa, ma ecco i miei due centesimi, che aggiungono filosoficamente alla risposta di Colin Hebert.

Ad alto livello la tua domanda affronta la differenza tra oggetti e tipi. Mentre ci sono molte macchine (oggetti), c'è solo una classe di auto (tipo). Dichiarare qualcosa come statico significa che stai operando nello spazio "tipo". Ce n'è solo uno. La parola chiave della classe di livello superiore definisce già un tipo nello spazio "type". Di conseguenza "Car di classe statica pubblica" è ridondante.


1
Sì. Per dirla in altro modo, le classi di livello superiore sono statiche per impostazione predefinita, quindi non è necessaria la parola chiave.
Warren Dew,

1
Bene, aggiungerei a quanto affermato da Warren Dew: "Le classi di livello superiore sono statiche per impostazione predefinita quando accedono ai membri statici".
Dexter,

1
Risposta sottovalutata. Una nuova parola chiave per forzare tutti i metodi di una classe a essere statici e il costruttore privato sarebbe carino. Non lo definirei statico perché è solo confuso.
G_V,

@G_V Anche se Java potrebbe creare un simile mostro, Java fa quasi del suo meglio per rendere le cose stupide difficili. La statica è una cattiva idea in generale, le lezioni statiche sono orribili (peggio dei singoli che sono essi stessi considerati un anti-schema). Molte persone non lo capiscono, quindi dargli una parola chiave sarebbe una pessima idea. Invece rendiamo le cose brutte difficili e lasciamo solo a quello. Si noti che non esiste nemmeno una parola chiave "Singleton". e nessuna parola chiave Property. Tutti questi causano un codice errato (anche se le persone usano ancora Proprietà così tanto che Java potrebbe anche supportarle)
Bill K

29

La classe con costruttore privato è statica.

Dichiara la tua classe in questo modo:

public class eOAuth {

    private eOAuth(){}

    public final static int    ECodeOauthInvalidGrant = 0x1;
    public final static int    ECodeOauthUnknown       = 0x10;
    public static GetSomeStuff(){}

}

e puoi usare senza inizializzazione:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...

3
Non è statico, ma contiene proprietà statiche. Se si scrive int finale pubblico ECodeOauthUnknown = 0x10; non è più statico.
user1883212

9
Nel caso qualcuno si stia chiedendo cosa sta succedendo qui, questo corrisponde alla definizione C # di una "classe statica" - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Data la definizione Java di "classe statica", tutte le classi non interne sono statiche (vedere le risposte dei fratelli).
Calum,

1
A parte @ user1883212 è giusto, direi anche che questa risposta confonde il lettore che il costruttore privato è in qualche modo importante qui, mentre in realtà non importa affatto.
tlwhitec,

Nel mondo .NET, se una classe è contrassegnata sia in astratto che in finale (l'effetto di una static classdichiarazione in C #), il compilatore non permetterà nemmeno al codice di dichiarare variabili di quel tipo, né lo usa come parametro di tipo generico. Una semplice mancanza di costruttori accessibili in una classe che potrebbe altrimenti essere istanziata o ereditata non precluderebbe la dichiarazione di variabili di quel tipo, né il suo uso come parametro di tipo generico.
supercat

Questa risposta è completamente errata. I costruttori privati ​​non hanno nulla a che fare con questo. Il codice è solo un esempio di una classe con nient'altro che attributi e metodi statici. Non ha nulla a che fare con le classi statiche.
Marchese di Lorne,

13

Certo che possono, ma solo classi annidate interne . Qui, significa che le istanze della classe nidificata non richiedono un'istanza chiusa della classe esterna.

Ma per le classi di alto livello, i progettisti del linguaggio non sono riusciti a pensare a qualcosa di utile da fare con la parola chiave, quindi non è permesso.


+1 nonostante la prima frase non sia esatta. Come afferma JLS: "Una classe interna è una classe nidificata che non è dichiarata staticamente o esplicitamente". (Solo terminologia, lo so ...)
user85421

7
Sebbene una classe di livello superiore non possa essere dichiarata static, a volte sarebbe logico poterla fare. Ad esempio, una classe contenente solo metodi di supporto statici non ha senso essere istanziati, ma il linguaggio Java non ti impedisce di farlo. Puoi rendere la classe non istanziabile (e praticamente 'statica') ad altre classi dichiarando il costruttore predefinito private, il che proibisce l'istanza perché nessun costruttore è visibile.
Iain Samuel McLean Elder,

12

È possibile creare una classe di utilità (che non può avere istanze create) dichiarando un tipo enum senza istanze. cioè stai specificatamente dichiarando che non ci sono casi.

public enum MyUtilities {;
   public static void myMethod();
}

25
un'enumerazione come tipo è un'aspettativa specifica: è un insieme enumerato di elementi. Usarlo per una "classe di utilità", quando altrimenti potresti semplicemente avere una classe con un costruttore privato, è semanticamente confuso.
Visionary Software Solutions,

5
@VisionarySoftwareSolutions Per me, questa specificità dice che non ci sono istanze di questa classe, piuttosto che rendere indirettamente impossibile creare istanze di una classe.
Peter Lawrey,

8
public class Outer {
   public static class Inner {}
}

... può essere dichiarato statico - purché sia ​​una classe membro.

Dal JLS:

Le classi membri possono essere statiche, nel qual caso non hanno accesso alle variabili di istanza della classe circostante; oppure possono essere classi interne (§8.1.3).

e qui:

La parola chiave statica può modificare la dichiarazione di un membro di tipo C all'interno del corpo di una classe non interna T. Il suo effetto è dichiarare che C non è una classe interna. Proprio come un metodo statico di T non ha un'istanza corrente di T nel suo corpo, anche C non ha un'istanza corrente di T, né ha istanze che si chiudono in modo lessicale.

Una parola chiave statica non avrebbe alcun senso per una classe di livello superiore, solo perché una classe di livello superiore non ha un tipo racchiuso.


Se non è interiore perché chiamarlo Inner? Nestedsarebbe stata una scelta meno confusa.
Marchese di Lorne,

5

Come spiegato sopra, una Classe non può essere statica a meno che non sia un membro di un'altra Classe.

Se stai cercando di progettare una classe "di cui non possono esserci più istanze", potresti voler esaminare il modello di progettazione "Singleton".

Informazioni per principianti Singleton qui .

Avvertimento:

Se stai pensando di usare il modello singleton, resisti con tutte le tue forze. È uno dei DesignPattern più facili da capire, probabilmente il più popolare e sicuramente il più abusato. (fonte: JavaRanch come linkato sopra)


4

Oltre a come Java definisce le classi interne statiche, esiste un'altra definizione di classi statiche secondo il mondo C # [1] . Una classe statica ha solo metodi (funzioni) statici ed è pensata per supportare la programmazione procedurale. Tali classi non sono realmente classi in quanto l'utente della classe è interessato solo alle funzioni di supporto e non alla creazione di istanze della classe. Mentre le classi statiche sono supportate in C #, in Java non esiste tale supporto diretto. Puoi comunque usare enum per imitare le classi statiche C # in Java in modo che un utente non possa mai creare istanze di una data classe (anche usando reflection) [2] :

public enum StaticClass2 {
    // Empty enum trick to avoid instance creation
    ; // this semi-colon is important

    public static boolean isEmpty(final String s) {
        return s == null || s.isEmpty();
    }
}

3

Tutto ciò che codifichiamo in Java va in una classe. Ogni volta che eseguiamo una classe JVM crea un'istanza di un oggetto. JVM può creare un numero di oggetti, per definizione Statico significa che hai lo stesso set di copie su tutti gli oggetti.

Quindi, se Java avrebbe consentito alla classe superiore di essere statica ogni volta che avvii un programma, crea un oggetto e continua a sovrascrivere nella stessa posizione di memoria.

Se stai semplicemente sostituendo l'oggetto ogni volta che lo esegui, qual è il punto di crearlo?

Questo è il motivo per cui Java si è sbarazzato dell'elettricità statica per la classe di livello superiore.

Potrebbero esserci ragioni più concrete, ma per me questo ha molto senso logico.


3
Le classi interne sono associate a classi esterne e questa è la ragione per cui possono essere statiche, poiché hai un oggetto diverso da cui dipendere.
user2626445,

1
Intendi "questo è il motivo per cui non possono essere statici".
Marchese di Lorne,

2

Le uniche classi che possono essere statiche sono le classi interne. Il seguente codice funziona perfettamente:

public class whatever {
    static class innerclass {
    }
}

Il punto delle classi interne statiche è che non hanno un riferimento all'oggetto classe esterno.


1
"statico interno" è una contraddizione in termini. 'statico' e 'interno' si escludono a vicenda. La parola che stai cercando è "nidificata", non "interiore".
Marchese di Lorne,

1

Penso che sia possibile facile come bere un bicchiere di caffè !. Dai un'occhiata a questo. Non usiamo esplicitamente parole chiave statiche durante la definizione della classe.

public class StaticClass {

    static private int me = 3;
    public static void printHelloWorld() {
       System.out.println("Hello World");
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

Non è una definizione di classe statica? Usiamo solo una funzione associata solo a una classe. Fai attenzione che in questo caso possiamo usare un'altra classe in quella nidificata. Guarda questo:

class StaticClass1 {

    public static int yum = 4;

    static void  printHowAreYou() {
        System.out.println("How are you?");
    }
}

public class StaticClass {

    static int me = 3; 
    public static void printHelloWorld() {
       System.out.println("Hello World");
       StaticClass1.printHowAreYou();
       System.out.println(StaticClass1.yum);
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

Penso che possiamo considerare tali classi come classe statica facendo riferimento alla definizione della classe statica non semplicemente usando una parola chiave statica come qualificatore.
Erfankam,

Assicurati di creare un costruttore privato, altrimenti potresti dirlo new StaticClass()e non ha molto senso. Con un costruttore privato non consentirebbe istanze di esso.
grinch,

1

PlatformUIIn Eclipse si può cercare una classe con metodi statici e costruttore privato con se stesso definitivo.

public final class <class name>
{
   //static constants
   //static memebers
}

0

se il vantaggio dell'uso di una classe statica non era di creare un'istanza di un oggetto e di utilizzare un metodo, dichiarare semplicemente la classe come pubblica e questo metodo come statico.

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.