Dlaczego nie możesz zadeklarować klasy jako statycznej w Javie?

459

Dlaczego nie możesz zadeklarować klasy jako statycznej w Javie?

Mariselvam
źródło
72
Kontr-pytanie: jaki byłby efekt, gdybyś zadeklarował klasę najwyższego poziomu static?
Joachim Sauer
3
Nie, nie możesz, z wyjątkiem statycznych klas wewnętrznych. Ale co chcesz z tym osiągnąć?
manolowar
60
@Jachach Sauer: C # interpretuje staticklasy jako abstract final, tzn. Nie można ich tworzyć i nie można przedłużać. Oznacza to, że mogą zawierać tylko elementy statyczne, co jest przydatne w przypadku klas zawierających tylko metody pomocnicze.
bcat
30
@bcat jest to prawdą w przypadku C #, ale klasa java może być abstrakcyjna lub końcowa, a nie obie. Aby zapobiec tworzeniu instancji klasy, można zadeklarować prywatnego konstruktora.
Lorenzo Polidori
7
@ JoachimSauer Proste, chciałbym zmusić wszystkich członków klasy do bycia statycznymi (być może nawet musiałbym zadeklarować każdą metodę lub właściwość).
hmartinezd

Odpowiedzi:

475

Tylko zagnieżdżone klasy mogą być statyczne. W ten sposób możesz użyć zagnieżdżonej klasy bez instancji klasy zewnętrznej.

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

Źródła:

Na ten sam temat:

Colin Hebert
źródło
3
+1, mimo że pierwsze zdanie nie jest dokładne. Jak samouczek mówi „Niestatyczne klasy zagnieżdżone nazywane są klasami wewnętrznymi”. (JLS: „Klasa wewnętrzna to klasa zagnieżdżona, która nie jest jawnie lub niejawnie zadeklarowana jako statyczna.”)
user85421,
74
Z pewnością masz rację; ale nie rozumiem, jak to odpowiada na pytanie
Joeri Hendrickx
2
@Carlos Heuberger, masz rację, zaktualizowałem post. @Jeri Hendrickx, Pytanie brzmiało: „Dlaczego klasy nie można uznać za statyczną…?”, Mogą i [przeczytaj mój post tutaj]. To objaśnienie użycia klas statycznych i dlaczego muszą to być klasy zagnieżdżone.
Colin Hebert
1
Podane tutaj rozwiązanie jest w porządku ... Ale wciąż zastanawiam się, czy ppl nie wyjaśnił logicznie, że klasa statyczna nie jest możliwa w java .. niektóre wyjaśnienia koncepcji OOP byłyby prawidłową odpowiedzią. Czekam na to
Punith Raj,
9
To prawda, ale pytanie, o którym myślisz, zwykle rozwiązuje się, gdy zaczynasz zadawać sobie pytanie, czym byłaby „klasa statyczna”. W java element statyczny oznacza, że ​​możesz uzyskać do niego dostęp / wywołać go bez instancji klasy zamykającej; co to może znaczyć, jeśli zastosujesz słowo kluczowe do samej klasy? Jakie masz zamiary? Czego byś oczekiwał Teraz, gdy masz już pojęcie, co to może być, jestem prawie pewien, że będzie to albo „nie miało sensu”, albo „dalekie” (to miałoby sens, ale koniec byłby tylko wyborem to zostało zrobione).
Colin Hebert
39

Klasy najwyższego poziomu są domyślnie statyczne. Klasy wewnętrzne są domyślnie niestatyczne. Możesz zmienić domyślne dla klas wewnętrznych, jawnie zaznaczając je jako statyczne. Klasy najwyższego poziomu, ze względu na to, że są najwyższego poziomu, nie mogą mieć niestatycznej semantyki, ponieważ nie ma klasy nadrzędnej, do której można by się odwoływać. Dlatego nie ma możliwości zmiany wartości domyślnej dla klas najwyższego poziomu.

nekromanta
źródło
14
»Klasy najwyższego poziomu są domyślnie statyczne.« To najlepsza odpowiedź. Są statyczne, ponieważ nie potrzebujesz żadnego wystąpienia, aby się do nich odnieść. Można się do nich odwoływać z dowolnego miejsca. Są w pamięci statycznej (jak w klasach pamięci C). - Jak zauważyli inni (Iain Elder w komentarzu do innej odpowiedzi), projektanci języka mogli pozwolić staticsłowu kluczowemu klasy najwyższego poziomu na oznaczenie i wymuszenie, że może on zawierać tylko elementy statyczne, a nie być tworzone; mogło to jednak pomylić ludzi, ponieważ staticma to inne znaczenie dla klas zagnieżdżonych.
Lumi,
35

Spóźniam się więc na przyjęcie, ale oto moje dwa centy - filozoficznie uzupełniające odpowiedź Colina Heberta.

Na wysokim poziomie twoje pytanie dotyczy różnicy między obiektami i typami. Chociaż istnieje wiele samochodów (obiektów), istnieje tylko jedna klasa samochodów (typ). Deklaracja czegoś jako statycznego oznacza, że ​​operujesz w przestrzeni „typowej”. Tam jest tylko jeden. Słowo kluczowe klasy najwyższego poziomu już definiuje typ w przestrzeni „type”. W rezultacie „publiczny samochód klasy statycznej” jest zbędny.

Eric Jankowski
źródło
1
Tak. Innymi słowy, klasy najwyższego poziomu są domyślnie statyczne, więc słowo kluczowe nie jest potrzebne.
Warren Dew
1
Dodałbym do tego, co powiedział Warren Dew - „klasy najwyższego poziomu są domyślnie statyczne podczas uzyskiwania dostępu do elementów statycznych”.
Dexter
1
Niedoceniana odpowiedź. Nowe słowo kluczowe, które wymusi, aby każda metoda w klasie była statyczna, a konstruktor prywatny byłby miły. Nie nazwałbym tego statycznym, ponieważ to po prostu mylące.
G_V,
@G_V Chociaż java może stworzyć takiego potwora, Java prawie wychodzi z drogi, aby utrudniać głupie rzeczy. Statyka jest ogólnie złym pomysłem, klasy statyczne są okropne (Gorzej niż singletony, które same są uważane za anty-wzór). Wiele osób tego nie rozumie, więc podanie słowa kluczowego byłoby bardzo złym pomysłem. Zamiast tego utrudniamy złe rzeczy i po prostu to zostawmy. Pamiętaj, że nie ma również słowa kluczowego „Singleton”. i brak słowa kluczowego Właściwość. Wszystko to powoduje zły kod (chociaż ludzie nadal używają Właściwości tak bardzo, że Java równie dobrze może je obsługiwać)
Bill K
29

Klasa z prywatnym konstruktorem jest statyczna.

Zadeklaruj swoją klasę w ten sposób:

public class eOAuth {

    private eOAuth(){}

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

}

i możesz używać bez inicjalizacji:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...
Sergey Vakulenko
źródło
3
Nie jest statyczny, ale zawiera właściwości statyczne. Jeśli napiszesz publiczny końcowy int ECodeOauthUnknown = 0x10; nie jest już statyczny.
user1883212
9
Jeśli ktoś zastanawia się, co się tutaj dzieje, odpowiada to definicji C # „klasy statycznej” - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Biorąc pod uwagę definicję Java „klasy statycznej”, wszystkie klasy inne niż wewnętrzne są statyczne (patrz odpowiedzi rodzeństwa).
Calum,
1
Poza tym @ user1883212 ma rację, powiedziałbym nawet, że ta odpowiedź dezorientuje czytelnika, że ​​prywatny konstruktor jest tutaj w jakiś sposób ważny, podczas gdy tak naprawdę nie ma znaczenia.
tlwhitec
W świecie .NET, jeśli klasa jest oznaczona zarówno jako abstrakcyjna, jak i końcowa (efekt static classdeklaracji w języku C #), kompilator nawet nie pozwoli kodowi deklarować zmiennych tego typu, ani nie użyje go jako parametru typu ogólnego. Sam brak dostępnych konstruktorów w klasie, które w innym przypadku byłyby tworzone lub dziedziczone, nie wykluczałby deklaracji zmiennych tego typu ani ich zastosowania jako parametru typu ogólnego.
supercat
Ta odpowiedź jest całkowicie niepoprawna. Prywatni konstruktorzy nie mają z tym nic wspólnego. Kod jest tylko przykładem klasy bez atrybutów i metod statycznych. Nie ma to nic wspólnego z klasami statycznymi.
Markiz Lorne
13

Pewnie, że mogą, ale tylko wewnętrzne klasy zagnieżdżone. Oznacza to, że instancje zagnieżdżonej klasy nie wymagają obejmującej instancji klasy zewnętrznej.

Ale w przypadku klas najwyższego poziomu projektanci języków nie mogli wymyślić nic użytecznego ze słowem kluczowym, więc jest to niedozwolone.

Michael Borgwardt
źródło
+1, mimo że pierwsze zdanie nie jest dokładne. Jak stwierdza JLS: „Klasa wewnętrzna jest klasą zagnieżdżoną, która nie jest jawnie lub niejawnie zadeklarowana jako statyczna”. (Tylko terminologia, wiem ...)
user85421
7
Chociaż nie można zadeklarować klasy najwyższego poziomu static, czasem warto mieć taką możliwość. Na przykład klasa zawierająca tylko statyczne metody pomocnicze nie ma sensu tworzyć instancji, ale język Java nie powstrzymuje cię przed zrobieniem tego. Możesz sprawić, by klasa nie była możliwa do utworzenia (i praktycznie „statyczna”) z innymi klasami, deklarując domyślny konstruktor private, który zabrania tworzenia instancji, ponieważ żaden konstruktor nie jest widoczny.
Iain Samuel McLean Starszy
12

Możesz utworzyć klasę narzędzia (w której nie można utworzyć instancji), deklarując typ wyliczenia bez instancji. tzn. w szczególności deklarujesz, że nie ma żadnych instancji.

public enum MyUtilities {;
   public static void myMethod();
}
Peter Lawrey
źródło
25
wyliczenie jako typ jest szczególnym oczekiwaniem: jest wyliczonym zestawem elementów. Używanie go do „klasy użytkowej”, gdy można by po prostu mieć klasę z prywatnym konstruktorem, jest semantycznie mylące.
Visionary Software Solutions
5
@VisionarySoftwareSolutions Według mnie ta specyfika mówi, że nie ma instancji tej klasy, zamiast pośrednio uniemożliwiać tworzenie instancji klasy.
Peter Lawrey,
8
public class Outer {
   public static class Inner {}
}

... można go uznać za statyczny - pod warunkiem, że jest klasą członkowską.

Z JLS:

Klasy członkowskie mogą być statyczne, w takim przypadku nie mają dostępu do zmiennych instancji otaczającej klasy; lub mogą to być klasy wewnętrzne (§ 8.1.3).

i tu:

Statyczne słowo kluczowe może modyfikować deklarację elementu typu C w ciele nie-wewnętrznej klasy T. Jego efektem jest zadeklarowanie, że C nie jest klasą wewnętrzną. Tak jak statyczna metoda T nie ma w swoim ciele bieżącej instancji T, tak C nie ma bieżącej instancji T, ani nie ma żadnych instancji leksykalnych.

Statyczne słowo kluczowe nie miałoby sensu dla klasy najwyższego poziomu, tylko dlatego, że klasa najwyższego poziomu nie ma typu otaczającego.

Andreas Dolk
źródło
Jeśli to nie wewnętrzne, dlaczego to nazwać Inner? Nestedbyłby mniej mylący wybór.
Markiz Lorne
5

Jak wyjaśniono powyżej, klasa nie może być statyczna, chyba że jest członkiem innej klasy.

Jeśli chcesz zaprojektować klasę „której nie może być wiele instancji”, możesz przyjrzeć się wzorowi projektowemu „Singleton”.

Informacje dla początkujących Singletona tutaj .

Zastrzeżenie:

Jeśli zastanawiasz się nad użyciem wzorca singletonu, oprzyj się z całych sił. Jest to jeden z najłatwiejszych do zrozumienia Wzorów Design, prawdopodobnie najpopularniejszy i zdecydowanie najbardziej nadużywany. (źródło: JavaRanch jak link powyżej)

S.Jones
źródło
4

Oprócz tego, jak Java definiuje statyczne klasy wewnętrzne, istnieje jeszcze inna definicja klas statycznych w świecie C # [1] . Klasa statyczna to taka, która ma wyłącznie metody statyczne (funkcje) i ma na celu wsparcie programowania proceduralnego. Takie klasy nie są tak naprawdę klasami, ponieważ użytkownik klasy jest zainteresowany jedynie funkcjami pomocniczymi, a nie tworzeniem instancji klasy. Podczas gdy klasy statyczne są obsługiwane w języku C #, nie ma takiej bezpośredniej obsługi w Javie. Możesz jednak użyć wyliczeń, aby naśladować klasy statyczne w języku C # w Javie, dzięki czemu użytkownik nigdy nie będzie mógł tworzyć wystąpień danej klasy (nawet używając odbicia) [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();
    }
}
oszustwa
źródło
3

Wszystko, co kodujemy w Javie, należy do klasy. Ilekroć uruchamiamy klasę, JVM tworzy obiekt. JVM może tworzyć wiele obiektów, z definicji Statyczny oznacza, że ​​masz ten sam zestaw kopii dla wszystkich obiektów.

Tak więc, jeśli Java pozwoliłaby, aby najwyższa klasa była statyczna za każdym razem, gdy uruchamiasz program, tworzy obiekt i przesuwa się do tej samej lokalizacji pamięci.

Jeśli po prostu wymieniasz obiekt za każdym razem, gdy go uruchamiasz, jaki jest sens jego tworzenia?

Dlatego właśnie Java pozbyła się statyczności dla klasy najwyższego poziomu.

Mogą istnieć bardziej konkretne powody, ale ma to dla mnie logiczny sens.

użytkownik2626445
źródło
3
Klasy wewnętrzne są powiązane z klasami zewnętrznymi i dlatego mogą być statyczne, ponieważ masz inny obiekt, na którym możesz polegać.
user2626445,
1
Masz na myśli „że jest powód, że może nie być statyczne”.
Markiz Lorne
2

Jedynymi klasami, które mogą być statyczne, są klasy wewnętrzne. Poniższy kod działa dobrze:

public class whatever {
    static class innerclass {
    }
}

Istotą statycznych klas wewnętrznych jest to, że nie mają one odniesienia do obiektu klasy zewnętrznej.

użytkownik2645256
źródło
1
„static static” jest wewnętrznie sprzecznością. „statyczny” i „wewnętrzny” wykluczają się wzajemnie. Szukane słowo to „zagnieżdżone”, a nie „wewnętrzne”.
Markiz Lorne
1

Myślę, że jest to możliwe tak łatwo, jak wypicie szklanki kawy !. Spójrz na to. Nie używamy statycznego słowa kluczowego jawnie podczas definiowania klasy.

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

Czy to nie jest definicja klasy statycznej? Po prostu używamy funkcji powiązanej tylko z klasą. Uważaj, aby w tym przypadku użyć innej klasy w tym zagnieżdżonym. Spójrz na to:

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
źródło
Myślę, że możemy uznać takie klasy za klasy statyczne, odwołując się do definicji klasy statycznej, a nie tylko poprzez użycie słowa kluczowego static jako kwalifikatora.
Erfankam
Pamiętaj, aby stworzyć prywatnego konstruktora, bo inaczej będziesz w stanie powiedzieć, new StaticClass()a to nie ma większego sensu. W przypadku prywatnego konstruktora nie zezwalałby na jego wystąpienia.
grinch
1

W PlatformUIEclipse można spojrzeć na klasę z metodami statycznymi i prywatnym konstruktorem, która sama jest ostateczna.

public final class <class name>
{
   //static constants
   //static memebers
}
użytkownik175881
źródło
0

jeśli korzyść z zastosowania klasy statycznej nie polegała na utworzeniu instancji obiektu i użyciu metody, wystarczy zadeklarować klasę jako publiczną, a tę metodę jako statyczną.

eeadev
źródło