'Statik' anahtar kelime bir sınıfta ne yapar?


444

Spesifik olarak, bu kodu deniyordum:

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

Ama hata verdi

Statik yöntem ana öğesinde statik olmayan alana erişilemiyor

Bu yüzden bunun beyanını değiştirdim clock:

static Clock clock = new Clock();

Ve işe yaradı. Bu anahtar kelimeyi bildirimin önüne koymak ne anlama gelir? Tam olarak ne yapacak ve / veya o nesneye yapılabilecekler açısından kısıtlayacak mı?


Bir kez daha CLASSLOADER başına sınıf başına bir statik örneği olduğunu unutmayın.
Javamann

Yanıtlar:


633

static üyeler belirli bir örnek yerine sınıfa aittir.

Bu, bir milyon sınıf örneği oluştursanız veya hiç oluşturmasanız bile, alanın yalnızca bir örneğinin static[1] var olduğu anlamına gelir . Tüm örnekler tarafından paylaşılacaktır.

Yana staticyöntemler de belirli bir örneğine aittir yok, bunlar örnek üyelerine başvuramaz. Verilen örnekte main, Hellosınıfın hangi örneğine (ve dolayısıyla sınıfın hangi örneğine Clock) başvurması gerektiğini bilmemektedir . staticüyeler yalnızca üyelere başvurabilir static. Örnek üyeler elbette staticüyelere erişebilir .

Yan not: Elbette, staticüyeler bir nesne başvurusu aracılığıyla örnek üyelere erişebilir .

Misal:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1]: Çalışma zamanı özelliklerine bağlı olarak, her ClassLoader veya AppDomain veya iş parçacığı için bir tane olabilir, ancak bu noktanın yanındadır.


5
.NET'te, bu davranışı, statik parçayı belirli iş parçacıkları için yerel yapan [ThreadStatic] özniteliğini kullanarak da değiştirebilirsiniz.
TheSoftwareJedi

4
Bu eski yazı olduğunu biliyorum ama benim gibi yeni başlayanlar için bu yararlı olabilir. stackoverflow.com/questions/7026507/…
user3526905

Özel bir değişken olduğu için instance.instanceField dosyasına erişemez misiniz? Yoksa nesneyi kendi sınıfının içinde başlattığınız için mi geçerli? Bana özyinelemeli bir kabus gibi geliyor ama ben bir Java acemi.
Matt Corby

Bir sınıfın statik üyesine 2 farklı iş parçacığı tarafından başvuruluyorsa, o statik üyenin kaç örneği vardır? 2 gibi hissediyorum ama aynı örneği iş parçacıkları arasında istiyorsanız o zaman uçucu anahtar kelime kullanılmalıdır. Bu doğru mu?
Dan

..ve sınıfın hiçbir örneği kalmadıysa değer korunur mu?
mckenzm

130

Bu, Hello'da yalnızca bir "saat" örneği olduğu anlamına gelir, "Hello" sınıfının her bir ayrı örneği için bir tane değil, veya daha fazlası, yani, "Merhaba" sınıfı.

Dolayısıyla, kodunuzun herhangi bir yerinde "yeni bir Merhaba" yapacak olsaydınız: A- ilk senaryoda (değişiklikten önce, "statik" kullanmadan), her "yeni bir Merhaba" her çağrıldığında yeni bir saat yapar, ancak B- ikinci senaryoda (değişiklikten sonra, "statik" kullanarak), her "yeni Hello" örneği yine de oluşturulan ilk ve aynı "saat" referansını paylaşır ve kullanır.

Eğer ana dışında bir yerde "saat" gerekmedikçe, bu da iyi çalışır:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}

Bunu yapmanın daha olağan yolu budur. main()Rutin kendine yeten olmalıdır.
Jason S

1
İkinci durumda, ana yöntem her çağrıldığında yeni bir Clock örneği oluşturur, değil mi?
Click Olumlu oy

2
İkinci durumda, saat statik, sadece bir kez yaratacaktır. Benim örneğimde, saatin ana telefonun içinde olduğu yerde, evet, her ana çağrıldığında yeni bir saat yaratacaktır. Ancak normalde main, program başlangıcında yalnızca bir kez çağrılır ve çıkıldığında her şey serbesttir.
Paul Tomblin

Ana yöntemde yeni bir saat yapmak nasıl mümkün değil? dediğiniz gibi main her çağrıldığında yeni oluşturacaktı, ama sadece bir ana yöntem var. bu ana yöntem farklı saat örneklerini nasıl ifade edebilir? Main'de saatin yeni bir örneğinin nasıl yapılacağını ve sayTime () yöntemini kullanmanın nasıl mümkün olduğunu anlamak biraz zor, ancak örneği anadan çıkarmak ve sayTime () kullanmak mümkün değil. main bir kez çağrıldığında her şey nasıl ücretsizdir? @PaulTomblin
ShakibaZar

@ user5621266 Sadece mainOP kullandığım için yöntemi kullandım . Bunun yerine, başka bir yerden çağrılan genel bir yöntemse ve Hello sınıfı bir kereden fazla başlatılırsa clock, statik olmadığı sürece her Hello örneği için bir Clock örneği oluşturabilir .
Paul Tomblin

97

staticAnahtar araçları, bir şey (bir alan, yöntem ya da iç içe geçmiş sınıf) ile ilgili olduğuna tip yerine herhangi bir örneği Çeşidi. Yani, örneğin, bir çağrı Math.sin(...)herhangi örneği olmadan Mathsınıfına, ve aslında sen edemez bir örneğini oluşturmakMath sınıfta.

Daha fazla bilgi için Oracle'ın Java Eğitimi'nin ilgili bölümüne bakın .


Kenar notu

Java, maalesef statik üyelere örnek üyeymiş gibi erişmenize izin verir , ör.

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

Bu , bir örnek yöntemi gibi görünmesini sağlarsleep , ancak aslında statik bir yöntemdir - her zaman geçerli iş parçacığını uyku durumuna getirir. Bunu arama kodunda açıkça belirtmek daha iyi bir uygulamadır:

// Clearer
Thread.sleep(5000);

1
Başka bir örnek: System.out.println () bir sınıf yöntemine benziyor , ancak aslında bir örnek yöntem. Out, System sınıfında bir PrintStream örneğidir.
Jiahui Zhang

@LeslieCheung: Hayır, benim için bir sınıf yöntemi gibi System.outdeğil, benim için bir tür adı gibi değil.
Jon Skeet

42

staticJava anahtar ait olduğu gibi değişken veya fonksiyon bu sınıfın tüm örnekleri arasında paylaşıldığı anlamına gelir türü değil, gerçek nesneler kendilerini.

Bir değişkeniniz varsa: private static int i = 0;ve i++bir örnekte ( ) değerini artırırsanız, değişiklik tüm örneklere yansıtılır. işimdi her durumda 1 olacak.

Statik yöntemler, bir nesne somutlaştırılmadan kullanılabilir.


4
"Tüm örnekler arasında paylaşılıyor" yanlış izlenim veriyor, IMO - nesnenin bir örneğine sahip olmanız gerektiğini gösteriyor .
Jon Skeet

1
(Oysa gerçekten olacaksa gerekmez herhangi statik alan vb ait olduğu, örnekler tip .)
Jon Skeet

@Jon Skeet static nesneye değil türe aittir? Daha fazla ayrıntı söyleyebilir misiniz? Veri türü gibi yazın: int, double, ...?
truongnm

@truongnm: Değişkeni / yöntemi bildiren sınıftaki gibi yazın.
Jon Skeet

26

Statik elemanların temel kullanımı ...

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

Başka bir sınıfa Merhaba sınıf örneği göndermeden tüm sınıf üyelerinde değerleri bu şekilde paylaşabilirsiniz. Ve whit static sınıf örneği oluşturmak gerekmez.

Hello hello = new Hello();
hello.staticValue = "abc";

Statik değerleri veya yöntemleri sınıf adına göre çağırabilirsiniz:

Hello.staticValue = "abc";

22

Statik, sınıfla ilişkili yöntemleri veya değişkenleri kullanmak için sınıfın bir örneğini oluşturmanız gerekmediği anlamına gelir. Örneğinizde şunları arayabilirsiniz:

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

doğrudan yerine:

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

Statik bir yöntemden (bir sınıfa ait olan), statik olmayan herhangi bir üyeye erişemezsiniz, çünkü değerleri sınıfın somutlaştırılmasına bağlıdır. Örnek üyesi olan statik olmayan bir Clock nesnesi, Hello sınıfınızın her örneği için farklı bir değere / referansa sahip olur ve bu nedenle ona sınıfın statik bölümünden erişemezsiniz.


Statik Bağlam için Harika Açıklama :)
Abdel-Raouf

20

Java'da statik:

Statik, Erişilemeyen Bir Değiştiricidir. Statik anahtar kelime, sınıf örneğine göre sınıfa aittir. bir Sınıfa bir Değişken veya Yöntem eklemek için kullanılabilir.

Statik anahtar kelime şunlarla kullanılabilir:

Yöntem

Değişken

Başka bir Sınıfın içine yerleştirilmiş sınıf

Başlatma Bloğu

Şununla KULLANILAMAZ:

Sınıf (İç içe değil)

inşaatçı

Arayüzler

Yöntem Yerel İç Sınıf (Fark sonra iç içe sınıf)

İç Sınıf yöntemleri

Örnek değişkenler

Yerel Değişkenler

Misal:

Yapıcıda artırılan count adında bir örnek değişkeni olan aşağıdaki örneği düşünün :

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Çıktı:

1 1 1

Örnek değişkeni, nesne oluşturma sırasında belleği aldığından, her nesne örnek değişkeninin kopyasına sahip olacaktır, eğer artırılırsa diğer nesnelere yansıtmaz.

Şimdi örnek değişkeni sayısını statik bir sayıyla değiştirirsek , program farklı çıktılar üretir:

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Çıktı:

1 2 3

Bu durumda statik değişken hafızayı yalnızca bir kez alır, herhangi bir nesne statik değişkenin değerini değiştirirse değerini korur.

Final ile Statik:

Nihai ve statik olarak bildirilen global değişken , tüm yürütme için değişmeden kalır. Çünkü, statik üyeler sınıf belleğinde saklanır ve tüm yürütmede yalnızca bir kez yüklenir. Sınıfın tüm nesneleri için ortaktır. Statik değişkenleri nihai olarak bildirirseniz, nesnelerin hiçbiri değerlerini nihai olarak değiştiremez. Bu nedenle, nihai ve statik olarak bildirilen değişkenlere bazen Sabitler denir. Varsayılan olarak son ve statik oldukları için tüm arabirim alanlarına sabitler denir.

resim açıklamasını buraya girin

Resim Kaynağı: Final Statik


15

Mevcut cevaplara eklemek için bir resimle deneyeyim:

TÜM tasarruf hesaplarına% 2 faiz uygulanmaktadır. Dolayısıyla statiktir .

Bir denge bireysel olmalıdır , bu yüzden statik değildir .

resim açıklamasını buraya girin


13

Bu tartışma, şu ana kadar sınıf yükleyici hususlarını göz ardı etmiştir. Kesin olarak, Java statik alanları belirli bir sınıf yükleyici için bir sınıfın tüm örnekleri arasında paylaşılır .


1
Bu, Merhdad'ın cevabı hakkındaki yorumlarda Apocalisp tarafından belirtildi.
Zach Langley

1
İyi bir nokta. Birçok insan bunu bilmiyor, ancak sınıf yükleyicileriyle uğraşmaya başladığınızda, çok önemli hale geliyor.
sleske

2
Hepsi doğru ama soruyu cevaplamıyor. Yorum olarak gönderilmiş olmalıdır.
Lorne Marquis

7

Bir sınıfa veya bir sınıf örneğine bir alan atanabilir. Varsayılan olarak alanlar örnek değişkenleridir. staticAlanı kullanmak bir sınıf değişkeni haline gelir, bu yüzden sadece bir tane vardır clock. Tek bir yerde değişiklik yaparsanız, her yerde görünür. Örnek değişkenleri birbirinden bağımsız olarak değiştirilir.


6

Anahtar kelime static, örneği değil, sınıfın kendisine ait bir alanı veya yöntemi belirtmek için kullanılır. Kodunuzu kullanarak, nesne Clockstatikse, Hellosınıfın tüm örnekleri bu Clockveri üyesini (alanını) ortak olarak paylaşır . Statik olmayan yaparsanız, her bir örneğinin Hellobenzersiz bir Clockalanı olabilir.

Sorun, kodu çalıştırabilmeniz için sınıfınıza bir ana yöntem Helloeklemenizdir. Buradaki problem, ana yöntemin statik olmasıdır ve bu nedenle, statik olmayan alanlara veya içindeki yöntemlere atıfta bulunamaz. Bunu iki şekilde çözebilirsiniz:

  1. HelloSınıfın tüm alanlarını ve yöntemlerini ana içinde belirtilebilecek şekilde statik yapın yöntemin . Bu gerçekten iyi bir şey değil (veya bir alanı ve / veya yöntemi statik hale getirmenin yanlış nedeni)
  2. HelloAna yöntem içinde sınıfınızın bir örneğini oluşturun ve tüm alanlarına ve yöntemlerine ilk başta amaçlandıkları şekilde erişin.

Sizin için bu, kodunuzda aşağıdaki değişiklik anlamına gelir:

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}

6

Java'da, staticanahtar kelime aşağıdakileri gösterdiği düşünülebilir:

"herhangi bir örnekle ilgili herhangi bir saygı veya ilişki olmadan"

staticBu şekilde düşünürseniz , karşılaşıldığı çeşitli bağlamlarda kullanımını anlamak daha kolay hale gelir:

  • Bir staticalan herhangi belirli bir örneğine göre bir sınıfa ait bir alandır

  • Bir staticyöntem, hiçbir fikri olmayan bir yöntemdir this; sınıfta tanımlanır ve ona bir referans iletilmediği sürece o sınıfın belirli bir örneğini bilmez

  • Bir staticüye sınıf, içine alan sınıfın bir örneğiyle ilgili herhangi bir kavram ya da bilgi içermeyen iç içe bir sınıftır (içine alan bir sınıf örneğine başvuru geçmedikçe)


5

Statik, saat üyesini örnek üyesi yerine sınıf üyesi yapar. Statik anahtar kelime olmadan, Hello sınıfının (saat üyesi değişkeni olan) bir örneğini oluşturmanız gerekir - ör.

Hello hello = new Hello();
hello.clock.sayTime();

5

statik yöntemler içinde tanımlandıkları sınıfın örnek değişkenlerini kullanmazlar. Bu sayfada farkın çok iyi bir açıklaması bulunabilir


5

"Yardımcı" sınıflarda statik yöntemler (sadece mümkünse) için bir beğeni geliştirdim.

Çağıran sınıfın, yardımcı sınıfın başka bir üye (örnek) değişkeni oluşturması gerekmez. Sadece yardımcı sınıfın yöntemlerini çağırırsınız. Ayrıca artık bir kurucuya ve üye (örnek) değişkenlere ihtiyacınız olmadığından yardımcı sınıf geliştirilir.

Muhtemelen başka avantajlar da vardır.


4
//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}

3

Statik üyelerin "bu" işaretçiye sahip olmadığını da düşünebilirsiniz. Tüm örnekler arasında paylaşılırlar.


3

Statik kavramları anlama

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

İkinci sınıf

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}

2

main() iki temel kısıtlamaya sahip statik bir yöntemdir:

  1. Statik yöntem, statik olmayan bir veri üyesi kullanamaz veya doğrudan statik olmayan yöntemi çağıramaz.
  2. this()ve super()statik bağlamda kullanılamaz.

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }

Çıktı: Derleme Zamanı Hatası


1

Statik Değişkenlere yalnızca statik yöntemlerle erişilebilir, bu nedenle statik değişkenleri bildirdiğimizde bu alıcı ve ayarlayıcı yöntemleri statik yöntemler olur

statik yöntemler, sınıf adını kullanarak erişebildiğimiz bir sınıf düzeyidir

Statik Değişkenler Harfleri ve Ayarlayıcıları için örnek:

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}

1

Burada bu kavram için 'statik' kelimesinin seçimi hakkında bir soru soruldu . Bu soruya cevap verildi, ama etimolojinin açıkça ele alındığını düşünmüyorum. Yani...


Bunun nedeni, C ile başlayan anahtar kelimelerin yeniden kullanılmasıdır.

C'deki (bir işlev gövdesi içinde) veri bildirimlerini göz önünde bulundurun:

    void f() {
        int foo = 1;
        static int bar = 2;
         :
    }

Foo değişkeni, işlev girildiğinde yığın üzerinde oluşturulur (ve işlev sonlandığında yok edilir). Aksine, bar her zaman oradadır, bu yüzden ortak İngilizce anlamında 'statik' - hiçbir yere gitmiyor.

Java ve benzer diller, veri için aynı kavramlara sahiptir. Veriler, sınıfın her örneği için (nesne başına) veya tüm sınıf için bir kez tahsis edilebilir. Java, C / C ++ programcıları için tanıdık bir sözdizimine sahip olmayı amaçladığından, 'statik' anahtar kelime burada uygundur.

    class C {
        int foo = 1;
        static int bar = 2;
         :
    }

Son olarak, yöntemlere geliyoruz.

    class C {
        int foo() { ... }
        static int bar() { ... }
         :
    }

Kavramsal olarak konuşursak, C sınıfının her örneği için bir foo () örneği vardır. Tüm C sınıfı için yalnızca bir bar () örneği vardır. Bu, veriler için tartıştığımız duruma paraleldir ve bu nedenle 'statik' ', özellikle de dilinize daha fazla ayrılmış anahtar kelime eklemek istemiyorsanız yine mantıklı bir seçimdir.

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.