Neden Java'da bir sınıfı statik olarak tanımlayamıyorsunuz?


459

Neden Java'da bir sınıfı statik olarak tanımlayamıyorsunuz?


72
Karşı soru: Eğer üst düzey bir sınıf ilan ettiyseniz, etkinin ne olmasını beklersiniz static?
Joachim Sauer

3
Hayır, yapamazsınız, statik iç sınıflar dışında. Fakat bununla neyi başarmak istiyorsunuz?
manolowar

60
@Joachim Sauer: C #, staticsınıfları abstract finalörneklendiriyor, yani somutlaştırılamaz ve genişletilemez. Bu, yalnızca yardımcı yöntemler içeren sınıflar için yararlı olan statik üyeleri içerebilecekleri anlamına gelir.
bcat

30
@bcat bu C # için geçerlidir, ancak bir java sınıfı ya soyut ya da final olabilir, her ikisi de değil. Bir sınıfın somutlaştırılmasını önlemek için özel bir kurucu bildirilebilir.
Lorenzo Polidori

7
@JoachimSauer Basit, sınıftaki tüm üyeyi statik olmaya zorlamak isterim (belki de her yöntem veya özellik hakkında beyan etmek zorunda kalırsınız).
hmartinezd

Yanıtlar:


475

Yalnızca iç içe sınıflar statik olabilir. Bunu yaparak, dış sınıfın bir örneğine sahip olmadan iç içe sınıfı kullanabilirsiniz.

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

Kaynaklar:

Aynı konuda:


3
İlk ifadenin tam olmamasına rağmen +1. Öğretici dediği gibi "Statik olmayan iç içe sınıflara iç sınıflar denir." (JLS: "Bir iç sınıf, açıkça veya dolaylı olarak statik olarak bildirilmeyen iç içe bir sınıftır.")
user85421

74
Kesinlikle haklısın; ama bunun soruyu nasıl cevapladığını göremiyorum
Joeri Hendrickx

2
@Carlos Heuberger, haklısın, yazıyı güncelledim. @Joeri Hendrickx, Soru şuydu: "Neden bir sınıf statik olarak ilan edilemez ..?", Yapabilirler ve [yazımı burada oku]. Bu, statik sınıfların kullanımı ve neden iç içe geçmiş olmaları gerektiği hakkında bir açıklamadır.
Colin Hebert

1
Burada verilen çözüm gayet iyi ... Ama hala y ppl mantıksal olarak statik sınıf mümkün değil java .. bazı OOPs kavram açıklama doğru cevap olacağını açıklamamış merak ediyorum. Bunu bekliyorum
Punith Raj

9
Bu doğru, ancak düşündüğünüz soru genellikle kendinize "statik sınıfın" ne olacağını sormaya başladığınızda kendini çözer. Java'da statik bir öğe, içine alan sınıfın bir örneği olmadan erişebildiğiniz / çağırabileceğiniz anlamına gelir; anahtar kelimeyi sınıfın kendisine uygularsanız bunun anlamı ne olabilir? Niyetin nedir? Ne beklerdiniz? Şimdi ne olabileceğine dair bir fikriniz olduğuna göre, eminim ya "gerçekten mantıklı değil" ya da "çok getirilmiş" olacaktır (mantıklı olurdu, ama sonunda sadece bir seçimdir) yapılmış).
Colin Hebert

39

Üst düzey sınıflar varsayılan olarak statiktir. İç sınıflar varsayılan olarak statik değildir. İç sınıflar için varsayılanı, açıkça statik olarak işaretleyerek değiştirebilirsiniz. Üst düzey sınıflar, üst düzey olmaları nedeniyle, statik olmayan semantiğe sahip olamazlar çünkü başvurulacak üst sınıf olamaz. Bu nedenle, üst düzey sınıflar için varsayılanı değiştirmenin bir yolu yoktur.


14
»Üst düzey sınıflar varsayılan olarak statiktir.« Bu en iyi yanıttır. Statiktirler çünkü onlara atıfta bulunmak için hiçbir şeyin örneğine ihtiyacınız yoktur. Her yerden başvurulabilirler. Onlar konum statik depolama (C depolama sınıfları gibi). - Diğerlerinin de belirttiği gibi (Iain Elder, başka bir cevaba yaptığı bir yorumda), staticüst düzey bir sınıftaki anahtar kelimenin, yalnızca statik üyeler içerebileceğini ve somutlaştırılamayacağını belirtmesine ve uygulamasına izin verebilirdi; ancak bu, staticiç içe dersler için farklı bir anlamı olduğu gibi insanları şaşırtabilir.
Lumi

35

Partiye geç geliyorum, ama işte iki sentim - felsefi olarak Colin Hebert'in cevabına ekliyor.

Yüksek düzeyde sorunuz nesneler ve türler arasındaki farkla ilgilenir. Birçok araba (nesne) varken, sadece bir Araba sınıfı (tipi) vardır. Bir şeyi statik olarak bildirmek, "type" alanında çalıştığınız anlamına gelir. Sadece bir tane var. Üst düzey sınıf anahtar kelimesi zaten "tür" alanında bir tür tanımlar. Sonuç olarak "genel statik sınıf Araba" gereksizdir.


1
Evet. Başka bir deyişle, üst düzey sınıflar varsayılan olarak statiktir, bu nedenle anahtar kelimeye gerek yoktur.
Warren Dew

1
Eh, Warren Dew'ın söylediklerine ekliyorum - "üst düzey sınıflar statik üyelere erişirken varsayılan olarak statiktir".
Dexter

1
Yetersiz cevap. Bir sınıftaki her yöntemi statik ve özel yapıcı olmaya zorlayan yeni bir anahtar kelime iyi olurdu. Statik olarak adlandırmam, çünkü bu sadece kafa karıştırıcı.
G_V

@G_V Java böyle bir canavar yaratabilse de, Java neredeyse aptalca şeyleri zorlaştırmak için kendi yolundan çıkıyor. Statik genel olarak kötü bir fikirdir, statik sınıflar korkunçtur (kendileri bir anti-desen olarak kabul edilen tektonlardan daha kötü). Birçok insan bunu anlamıyor, bu yüzden bir anahtar kelime vermek çok kötü bir fikir olurdu. Bunun yerine, kötü şeyleri zorlaştırıyoruz ve sadece bu konuda bırakıyoruz. Ayrıca "Singleton" anahtar kelimesi olmadığını unutmayın. ve Özellik anahtar kelimesi içermez. Bunların hepsi kötü kodlara neden oluyor (Her ne kadar insanlar hala Özellikleri o kadar çok kullanıyorlarsa da Java onları da destekleyebilir)
Bill K

29

Özel yapıcılı sınıf statiktir.

Sınıfınızı şöyle ilan edin:

public class eOAuth {

    private eOAuth(){}

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

}

ve başlatma olmadan kullanabilirsiniz:

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

3
Statik değil, ancak statik özellikler içerir. Genel son int yazarsanız ECodeOauthUnknown = 0x10; artık statik değil.
user1883212

9
Herkes burada neler olduğunu merak ediyorsa, bu bir "statik sınıf" C # tanımıyla eşleşir - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Java'nın "statik sınıf" tanımı göz önüne alındığında, tüm iç olmayan sınıflar statiktir (bkz. Kardeş cevaplar).
Calum

1
@ User1883212'nin yanı sıra, bu cevabın okuyucunun özel kurucunun burada bir şekilde önemli olduğunu ve hatta hiç önemli olmadığını karıştırdığını bile söyleyebilirim.
tlwhitec

.NET dünyasında, bir sınıf hem soyut hem de son olarak işaretlenmişse ( static classC # 'da bir bildirimin etkisi ), derleyici kodun bu türdeki değişkenleri bildirmesine veya genel bir tür parametresi olarak kullanmasına bile izin vermez. Bir sınıfta başka türlü somutlaştırılabilen veya devralınabilen yalnızca erişilebilir kurucuların eksikliği, bu türdeki değişkenlerin bildirimini veya jenerik tip parametresi olarak kullanılmasını engellemez.
supercat

Bu cevap tamamen yanlış. Özel yapımcıların bununla hiçbir ilgisi yoktur. Kod yalnızca statik öznitelikler ve yöntemler dışında hiçbir şeye sahip olmayan bir sınıf örneğidir. Statik sınıflarla hiçbir ilgisi yoktur.
Lorne Marquis

13

Elbette yapabilirler, ama sadece içe sınıflar. Burada, iç içe sınıfın örneklerinin dış sınıfın kapalı bir örneğini gerektirmediği anlamına gelir.

Ancak üst düzey sınıflar için, dil tasarımcıları anahtar kelimeyle ilgili yararlı bir şey düşünemedi, bu yüzden izin verilmiyor.


İlk ifadenin tam olmamasına rağmen +1. JLS'in belirttiği gibi: "Bir iç sınıf, açıkça veya dolaylı olarak statik olarak bildirilmeyen iç içe bir sınıftır." (Sadece terminoloji, biliyorum ...)
user85421

7
Üst düzey bir sınıf ilan edilemese staticde bazen yapabilmek mantıklı olur. Örneğin, yalnızca statik yardımcı yöntemleri içeren bir sınıfın somutlaştırılması anlamlı değildir, ancak Java dili bunu yapmanızı engellemez. privateHiçbir kurucu görünür olmadığından somutlaştırmayı yasaklayan varsayılan kurucuyu bildirerek sınıfı diğer sınıflara somutlaştırılamaz (ve pratik olarak 'statik') yapabilirsiniz .
Iain Samuel McLean Elder

12

Örnek içermeyen bir numaralandırma türü bildirerek (örnek oluşturulamayan) bir yardımcı program sınıfı oluşturabilirsiniz. yani, hiçbir örnek olmadığını özellikle belirtiyorsunuz.

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

25
bir tür olarak numaralandırma belirli bir beklenti: numaralandırılmış bir öğeler kümesidir. Özel bir kurucu ile bir sınıfa sahip olabileceğiniz bir "yardımcı sınıf" için kullanmak semantik olarak kafa karıştırıcıdır.
Vizyoner Yazılım Çözümleri

5
@VisionarySoftwareSolutions Bana göre, bu özgüllük dolaylı olarak bir sınıf örneği oluşturmayı imkansız kılmaktan ziyade bu sınıfın hiçbir örneği olmadığını söylüyor.
Peter Lawrey

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

... üye sınıf olduğu sürece statik olarak bildirilebilir.

JLS'den:

Üye sınıfları statik olabilir, bu durumda çevreleyen sınıfın örnek değişkenlerine erişimleri yoktur; ya da iç sınıflar olabilirler (§8.1.3).

ve burada:

Statik anahtar kelime, iç olmayan bir sınıf T'nin gövdesi içindeki bir üye tip C'nin bildirimini değiştirebilir. Etkisi, C'nin bir iç sınıf olmadığını beyan etmektir. Tıpkı statik bir T metodunun vücudunda şu anki T örneği bulunmadığı gibi, C'nin de şu anki T örneği yoktur ya da sözlüksel olarak çevreleyen örnekleri yoktur.

Statik bir anahtar kelime, üst düzey bir sınıfın kapalı türü olmadığından, üst düzey bir sınıf için anlamlı olmaz.


Eğer içsel değilse neden aramalısınız Inner? Nesteddaha az kafa karıştırıcı bir seçim olurdu.
Lorne Marquis

5

Yukarıda açıklandığı gibi, bir Sınıf başka bir Sınıfın üyesi olmadığı sürece statik olamaz.

"Birden fazla örneği olamaz" bir sınıf tasarlamak istiyorsanız, "Singleton" tasarım desenine bakmak isteyebilirsiniz.

Acemi Singleton bilgisi burada .

Uyarı:

Eğer tekli kalıbı kullanmayı düşünüyorsanız, tüm gücünüze karşı koyun. Muhtemelen en popüler ve kesinlikle en çok istismar edilen, anlaşılması en kolay DesignPatterns'lerden biridir. (kaynak: yukarıda bağlandığı gibi JavaRanch)


4

Java'nın statik iç sınıfları nasıl tanımladığına ek olarak, C # dünyasına [1] göre statik sınıfların başka bir tanımı daha vardır . Statik sınıf, yalnızca statik yöntemlere (işlevlere) sahip olan sınıftır ve prosedürel programlamayı desteklemek içindir. Bu tür sınıflar, sınıfın kullanıcısının sınıf yardımcıları oluşturmakla değil, yalnızca yardımcı işlevlerle ilgilenmesi açısından gerçekten sınıflar değildir. Statik sınıflar C # 'da desteklenirken, Java'da böyle bir doğrudan destek yoktur. Bununla birlikte, kullanıcıların belirli bir sınıfın örneklerini (yansımayı kullanarak bile) oluşturamaması için Java'da C # statik sınıflarını taklit etmek için sıralamalar kullanabilirsiniz [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

Java'da kodladığımız her şey bir sınıfa girer. Ne zaman bir sınıf çalıştırsak, JVM bir nesneyi başlatır. JVM bir dizi nesne oluşturabilir, tanımı gereği Statik, tüm nesnelere aynı kopya kümesine sahip olduğunuz anlamına gelir.

Dolayısıyla, bir programı her çalıştırdığınızda Java üst sınıfın statik olmasına izin verirse, bir Nesne oluşturur ve aynı Bellek Konumunda geçersiz kılmaya devam eder.

Nesneyi her çalıştırdığınızda değiştiriyorsanız, onu yaratmanın anlamı nedir?

Java'nın üst düzey sınıf için statikten kurtulmasının nedeni budur.

Daha somut nedenler olabilir ama bu benim için çok mantıklı geliyordu.


3
İç sınıflar dış sınıflarla ilişkilidir ve bu nedenle bağımlı olmanız gereken farklı bir nesneniz olduğu için statik olabilirler.
user2626445

1
Sen onlar yapabilirsiniz nedeni olduğu anlamına değil statik olması '.
Lorne Marquis

2

Statik olabilen tek sınıflar iç sınıflardır. Aşağıdaki kod iyi çalışıyor:

public class whatever {
    static class innerclass {
    }
}

Statik iç sınıfların amacı, dış sınıf nesnesine bir referansları olmamasıdır.


1
'statik iç' bir çelişkidir. 'statik' ve 'iç' birbirini dışlar. Aradığınız kelime 'iç' değil, 'iç içe'.
Lorne Marquis

1

Bence bu bir bardak kahve içmek kadar kolay! Sadece şuna bir bakın. Sınıfı tanımlarken statik anahtar kelimeyi açıkça kullanmıyoruz.

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

Bu statik sınıfın bir tanımı değil mi? Sadece bir sınıfa bağlı bir fonksiyon kullanıyoruz. Bu durumda yuvalanmış başka bir sınıf kullanabileceğimizi unutmayın. Şuna bak:

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

Ben sadece statik anahtar sözcük niteleyici olarak kullanarak değil, statik sınıf tanımı bakın statik sınıf olarak bu sınıfları düşünebilirsiniz düşünüyorum.
Erfankam

Özel bir kurucu oluşturduğunuzdan emin olun, yoksa söyleyebileceksiniz new StaticClass()ve bu gerçekten çok mantıklı değil. Özel bir kurucu ile onun örneklerine izin vermezdi.
grinch

1

PlatformUIEclipse'de statik yöntemlere sahip bir sınıf ve özel yapıcı son olarak bakılabilir .

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

0

statik sınıf kullanmanın yararı bir nesneyi örneklemek ve bir yöntem kullanmak değilse, sınıfı genel olarak ve bu yöntemi statik olarak bildirmeniz yeterliyse.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.