Warum können Sie eine Klasse in Java nicht als statisch deklarieren?

459

Warum können Sie eine Klasse in Java nicht als statisch deklarieren?

Mariselvam
quelle
72
Gegenfrage: Was würden Sie erwarten, wenn Sie eine Klasse der obersten Ebene deklarieren würden static?
Joachim Sauer
3
Nein, das kannst du nicht, außer für statische innere Klassen. Aber was wollen Sie damit erreichen?
Manolowar
60
@ Joachim Sauer: Nun, C # interpretiert staticKlassen so abstract final, dass sie nicht instanziiert und nicht erweitert werden können. Dies bedeutet, dass sie nur statische Elemente enthalten können. Dies ist nützlich für Klassen, die nur Hilfsmethoden enthalten.
bcat
30
@bcat Dies gilt für C #, aber eine Java-Klasse kann entweder abstrakt oder endgültig sein, nicht beide. Um zu verhindern, dass eine Klasse instanziiert wird, kann ein privater Konstruktor deklariert werden.
Lorenzo Polidori
7
@JoachimSauer Einfach, ich würde gerne alle Mitglieder in der Klasse dazu zwingen, statisch zu sein (möglicherweise muss sogar für jede Methode oder Eigenschaft deklariert werden).
Hmartinezd

Antworten:

475

Nur verschachtelte Klassen können statisch sein. Auf diese Weise können Sie die verschachtelte Klasse verwenden, ohne eine Instanz der äußeren Klasse zu haben.

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

Quellen:

Zum gleichen Thema:

Colin Hebert
quelle
3
+1, obwohl der erste Satz nicht genau ist. Im Lernprogramm heißt es: "Nicht statische verschachtelte Klassen werden als innere Klassen bezeichnet." (JLS: "Eine innere Klasse ist eine verschachtelte Klasse, die nicht explizit oder implizit als statisch deklariert ist.")
user85421
74
Sie haben mit Sicherheit recht; aber ich sehe nicht, wie dies die Frage beantwortet
Joeri Hendrickx
2
@ Carlos Heuberger, du hast recht, ich habe den Beitrag aktualisiert. @Joeri Hendrickx, Die Frage war: "Warum kann eine Klasse nicht als statisch deklariert werden?", Können sie, und [lesen Sie meinen Beitrag hier]. Dies ist eine Erklärung für die Verwendung statischer Klassen und warum sie verschachtelte Klassen sein müssen.
Colin Hebert
1
Die hier gegebene Lösung ist in Ordnung ... Aber ich frage mich immer noch, ob Sie nicht logisch erklärt haben, dass statische Klassen in Java nicht möglich sind. Einige Erklärungen zum OOP-Konzept wären die richtige Antwort. Ich
warte
9
Das stimmt, aber die Frage, über die Sie nachdenken, löst sich normalerweise von selbst, wenn Sie sich fragen, was eine "statische Klasse" wäre. In Java bedeutet ein statisches Element, dass Sie ohne eine Instanz der einschließenden Klasse darauf zugreifen / es aufrufen können. Was könnte das möglicherweise bedeuten, wenn Sie das Schlüsselwort auf die Klasse selbst anwenden? Was sind deine Absichten? Was würden Sie erwarten? Jetzt, da Sie eine Vorstellung davon haben, was es sein könnte, bin ich mir ziemlich sicher, dass es entweder "nicht wirklich sinnvoll" oder "weit hergeholt" sein wird (es würde Sinn machen, aber am Ende ist es nur eine Wahl das wurde gemacht).
Colin Hebert
39

Klassen der obersten Ebene sind standardmäßig statisch. Innere Klassen sind standardmäßig nicht statisch. Sie können die Standardeinstellung für innere Klassen ändern, indem Sie sie explizit als statisch markieren. Klassen der obersten Ebene können aufgrund ihrer obersten Ebene keine nicht statische Semantik haben, da es keine übergeordnete Klasse geben kann, auf die Bezug genommen werden kann. Daher gibt es keine Möglichkeit, die Standardeinstellung für Klassen der obersten Ebene zu ändern.

Nekromant
quelle
14
»Klassen der obersten Ebene sind standardmäßig statisch.« Dies ist die beste Antwort. Sie sind statisch, da Sie keine Instanz von irgendetwas benötigen, um auf sie zu verweisen. Sie können von überall her abgerufen werden. Sie befinden sich im statischen Speicher (wie in C-Speicherklassen). - Wie andere angemerkt haben (Iain Elder in einem Kommentar zu einer anderen Antwort), hätten die Sprachdesigner zulassen können, dass das staticSchlüsselwort in einer Klasse der obersten Ebene angibt und erzwingt, dass es möglicherweise nur statische Elemente enthält und nicht instanziiert wird. das hätte die Leute jedoch verwirren können, da statices für verschachtelte Klassen eine andere Bedeutung hat.
Lumi
35

Also komme ich zu spät zur Party, aber hier sind meine zwei Cent - eine philosophische Ergänzung zu Colin Heberts Antwort.

Auf hoher Ebene befasst sich Ihre Frage mit dem Unterschied zwischen Objekten und Typen. Während es viele Autos (Objekte) gibt, gibt es nur eine Autoklasse (Typ). Wenn Sie etwas als statisch deklarieren, bedeutet dies, dass Sie im Bereich "Typ" arbeiten. Es gibt nur eins. Das Schlüsselwort class der obersten Ebene definiert bereits einen Typ im Bereich "type". Infolgedessen ist "Auto der öffentlichen statischen Klasse" überflüssig.

Eric Jankowski
quelle
1
Ja. Anders ausgedrückt, Klassen der obersten Ebene sind standardmäßig statisch, sodass das Schlüsselwort nicht erforderlich ist.
Warren Dew
1
Nun, ich würde zu dem, was Warren Dew sagte, hinzufügen: "Klassen der obersten Ebene sind standardmäßig statisch, wenn auf statische Mitglieder zugegriffen wird."
Dexter
1
Unterschätzte Antwort. Ein neues Schlüsselwort, mit dem jede Methode in einer Klasse statisch und der Konstruktor privat erzwungen wird, wäre hilfreich. Ich würde es nicht statisch nennen, weil das nur verwirrend ist.
G_V
@G_V Obwohl Java solch ein Monster erschaffen könnte, tut Java fast alles, um dumme Dinge schwierig zu machen. Statik ist im Allgemeinen eine schlechte Idee, statische Klassen sind schrecklich (schlimmer als Singletons, die selbst als Anti-Pattern gelten). Viele Leute verstehen das nicht, daher wäre es eine sehr schlechte Idee, ihm ein Schlüsselwort zu geben. Stattdessen machen wir schlechte Dinge schwierig und belassen es dabei. Beachten Sie, dass es auch kein "Singleton" -Schlüsselwort gibt. und kein Property-Schlüsselwort. Diese alle verursachen schlechten Code (obwohl die Leute Eigenschaften immer noch so oft verwenden, dass Java sie genauso gut unterstützen könnte)
Bill K
29

Klasse mit privatem Konstruktor ist statisch.

Erkläre deine Klasse so:

public class eOAuth {

    private eOAuth(){}

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

}

und Sie können ohne Initialisierung verwenden:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...
Sergey Vakulenko
quelle
3
Es ist nicht statisch, sondern enthält statische Eigenschaften. Wenn Sie public final schreiben int ECodeOauthUnknown = 0x10; es ist nicht mehr statisch.
user1883212
9
Falls sich jemand fragt, was hier vor sich geht, entspricht dies der C # -Definition einer "statischen Klasse" - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Angesichts der Java-Definition von "statische Klasse" sind alle nicht-inneren Klassen statisch (siehe Antworten von Geschwistern).
Calum
1
Abgesehen davon, dass @ user1883212 richtig ist, würde ich sogar sagen, dass diese Antwort den Leser verwirrt, dass der private Konstruktor hier irgendwie wichtig ist, während es wirklich überhaupt keine Rolle spielt.
tlwhitec
Wenn in der .NET-Welt eine Klasse sowohl als abstrakt als auch als endgültig markiert ist (der Effekt einer static classDeklaration in C #), lässt der Compiler nicht einmal zu, dass Code Variablen dieses Typs deklariert oder als generischen Typparameter verwendet. Ein bloßer Mangel an zugänglichen Konstruktoren in einer Klasse, die andernfalls entweder instanziiert oder geerbt werden könnten, würde weder die Deklaration von Variablen dieses Typs noch deren Verwendung als generischer Typparameter ausschließen.
Supercat
Diese Antwort ist völlig falsch. Private Konstrukteure haben nichts damit zu tun. Der Code ist nur ein Beispiel für eine Klasse mit nur statischen Attributen und Methoden. Es hat nichts mit statischen Klassen zu tun.
Marquis von Lorne
13

Sicher können sie, aber nur inner verschachtelte Klassen. Dort bedeutet dies, dass Instanzen der verschachtelten Klasse keine umschließende Instanz der äußeren Klasse benötigen.

Für Klassen der obersten Ebene konnten sich die Sprachdesigner jedoch nichts Nützliches für das Schlüsselwort vorstellen, daher ist dies nicht zulässig.

Michael Borgwardt
quelle
+1, obwohl der erste Satz nicht genau ist. Wie das JLS feststellt: "Eine innere Klasse ist eine verschachtelte Klasse, die nicht explizit oder implizit als statisch deklariert ist." (Nur Terminologie, ich weiß ...)
user85421
7
Obwohl eine Klasse der obersten Ebene nicht deklariert werden kann static, ist es manchmal sinnvoll, dies zu können. Zum Beispiel macht es keinen Sinn, eine Klasse zu instanziieren, die nur statische Hilfsmethoden enthält, aber die Java-Sprache hindert Sie nicht daran, dies zu tun. Sie können die Klasse für andere Klassen nicht instanziierbar (und praktisch 'statisch') machen, indem Sie den Standardkonstruktor deklarieren private, der die Instanziierung verbietet, da kein Konstruktor sichtbar ist.
Iain Samuel McLean Elder
12

Sie können eine Dienstprogrammklasse erstellen (für die keine Instanzen erstellt werden können), indem Sie einen Aufzählungstyp ohne Instanzen deklarieren. dh Sie erklären ausdrücklich, dass es keine Instanzen gibt.

public enum MyUtilities {;
   public static void myMethod();
}
Peter Lawrey
quelle
25
Eine Aufzählung als Typ ist eine bestimmte Erwartung: Es handelt sich um eine Aufzählung von Elementen. Die Verwendung für eine "Utility-Klasse", wenn Sie sonst nur eine Klasse mit einem privaten Konstruktor haben könnten, ist semantisch verwirrend.
Visionary Software Solutions
5
@VisionarySoftwareSolutions Für mich bedeutet diese Spezifität, dass es keine Instanzen dieser Klasse gibt, anstatt indirekt das Erstellen von Instanzen einer Klasse unmöglich zu machen.
Peter Lawrey
8
public class Outer {
   public static class Inner {}
}

... kann als statisch deklariert werden - solange es sich um eine Mitgliedsklasse handelt.

Aus dem JLS:

Mitgliedsklassen können statisch sein. In diesem Fall haben sie keinen Zugriff auf die Instanzvariablen der umgebenden Klasse. oder sie können innere Klassen sein (§8.1.3).

und hier:

Das statische Schlüsselwort kann die Deklaration eines Elementtyps C innerhalb des Körpers einer nicht inneren Klasse T ändern. Es bewirkt, dass C keine innere Klasse ist. So wie eine statische Methode von T keine aktuelle Instanz von T in ihrem Körper hat, hat C auch keine aktuelle Instanz von T und auch keine lexikalisch einschließenden Instanzen.

Ein statisches Schlüsselwort wäre für eine Klasse der obersten Ebene nicht sinnvoll, nur weil eine Klasse der obersten Ebene keinen umschließenden Typ hat.

Andreas Dolk
quelle
Wenn es nicht innerlich ist, warum nennst du es? Inner du ? Nestedwäre eine weniger verwirrende Wahl gewesen.
Marquis von Lorne
5

Wie oben erläutert, kann eine Klasse nur statisch sein, wenn sie Mitglied einer anderen Klasse ist.

Wenn Sie eine Klasse entwerfen möchten, "von der es nicht mehrere Instanzen geben kann", sollten Sie sich das Entwurfsmuster "Singleton" ansehen.

Anfänger Singleton Infos hier .

Vorbehalt:

Wenn Sie daran denken, das Singleton-Muster zu verwenden, widersetzen Sie sich mit aller Kraft. Es ist eines der am einfachsten zu verstehenden DesignPatterns, wahrscheinlich das beliebteste und definitiv das am meisten missbrauchte. (Quelle: JavaRanch wie oben verlinkt)

S. Jones
quelle
4

Zusätzlich zu der Definition statischer innerer Klassen durch Java gibt es eine andere Definition statischer Klassen gemäß der C # -Welt [1] . Eine statische Klasse hat nur statische Methoden (Funktionen) und soll die prozedurale Programmierung unterstützen. Solche Klassen sind nicht wirklich Klassen, da der Benutzer der Klasse nur an den Hilfsfunktionen interessiert ist und nicht daran, Instanzen der Klasse zu erstellen. Während statische Klassen in C # unterstützt werden, gibt es in Java keine solche direkte Unterstützung. Sie können jedoch Aufzählungen verwenden, um statische C # -Klassen in Java nachzuahmen, sodass ein Benutzer niemals Instanzen einer bestimmten Klasse erstellen kann (auch nicht unter Verwendung von 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();
    }
}
Täuschungen
quelle
3

Alles, was wir in Java codieren, wird in eine Klasse eingeteilt. Immer wenn wir eine Klasse ausführen, instanziiert JVM ein Objekt. JVM kann eine Reihe von Objekten erstellen. Per Definition bedeutet statisch, dass Sie für alle Objekte den gleichen Kopiersatz haben.

Wenn Java also zugelassen hätte, dass die Top-Klasse beim Ausführen eines Programms statisch ist, wird ein Objekt erstellt und derselbe Speicherort überschrieben.

Wenn Sie das Objekt nur jedes Mal ersetzen, wenn Sie es ausführen, wozu wird es dann erstellt?

Das ist der Grund, warum Java die Statik für die Top-Level-Klasse beseitigt hat.

Es mag konkretere Gründe geben, aber das ergab für mich einen logischen Sinn.

user2626445
quelle
3
Innere Klassen sind äußeren Klassen zugeordnet, und aus diesem Grund können sie statisch sein, da Sie ein anderes Objekt haben, von dem Sie abhängen können.
user2626445
1
Sie meinen "das ist der Grund, warum sie nicht statisch sein können".
Marquis von Lorne
2

Die einzigen Klassen, die statisch sein können, sind innere Klassen. Der folgende Code funktioniert einwandfrei:

public class whatever {
    static class innerclass {
    }
}

Der Punkt statischer innerer Klassen ist, dass sie keinen Verweis auf das äußere Klassenobjekt haben.

user2645256
quelle
1
'statisches Inneres' ist ein Widerspruch. 'statisch' und 'inner' schließen sich gegenseitig aus. Das gesuchte Wort ist "verschachtelt", nicht "inner".
Marquis von Lorne
1

Ich denke, das ist so einfach wie ein Glas Kaffee! Schauen Sie sich das an. Bei der Definition der Klasse wird das statische Schlüsselwort nicht explizit verwendet.

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

Ist das nicht eine Definition der statischen Klasse? Wir verwenden nur eine Funktion, die nur an eine Klasse gebunden ist. Achten Sie darauf, dass wir in diesem Fall eine andere Klasse in dieser verschachtelten Klasse verwenden können. Schau dir das an:

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);
    }
}
Erfankam
quelle
Ich denke, wir können solche Klassen als statische Klasse betrachten, indem wir auf die statische Klassendefinition verweisen und nicht nur das statische Schlüsselwort als Qualifikationsmerkmal verwenden.
Erfankam
Stellen Sie sicher, dass Sie einen privaten Konstruktor erstellen, sonst könnten Sie sagen, new StaticClass()und das macht nicht wirklich viel Sinn. Mit einem privaten Konstruktor würde es keine Instanzen davon zulassen.
grinch
1

Man kann schauen , PlatformUIfür eine Klasse in Eclipse mit statischen Methoden und privatem Konstruktor mit selbst endgültig zu sein.

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

Wenn der Vorteil der Verwendung einer statischen Klasse nicht darin bestand, ein Objekt zu instanziieren und eine Methode zu verwenden, deklarieren Sie die Klasse einfach als öffentlich und diese Methode als statisch.

eeadev
quelle