Apa yang dilakukan kata kunci 'statis' di kelas?

444

Untuk lebih spesifik, saya mencoba kode ini:

package hello;

public class Hello {

    Clock clock = new Clock();

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

Tapi itu memberi kesalahan

Tidak dapat mengakses bidang non-statis dalam metode statis utama

Jadi saya mengubah pernyataan clockmenjadi ini:

static Clock clock = new Clock();

Dan itu berhasil. Apa artinya menempatkan kata kunci itu sebelum deklarasi? Apa tepatnya yang akan dilakukannya dan / atau batasi dalam hal apa yang dapat dilakukan untuk objek itu?

Klik Upvote
sumber
Sekali lagi ingat bahwa ada satu contoh statis per kelas per CLASSLOADER.
Javamann

Jawaban:

633

static anggota menjadi anggota kelas, bukan contoh khusus.

Ini berarti bahwa hanya ada satu instance dari staticbidang yang ada [1] bahkan jika Anda membuat sejuta instance dari kelas atau Anda tidak membuat apapun. Ini akan dibagikan oleh semua instance.

Karena staticmetode juga bukan milik instance tertentu, mereka tidak dapat merujuk ke anggota instance. Dalam contoh yang diberikan, maintidak tahu instance Hellokelas apa (dan karenanya instance Clockkelas mana) yang harus dirujuk. staticanggota hanya dapat merujuk ke staticanggota. Anggota Instance dapat, tentu saja, mengakses staticanggota.

Catatan samping: Tentu saja, staticanggota dapat mengakses anggota contoh melalui referensi objek .

Contoh:

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]: Bergantung pada karakteristik runtime, itu bisa satu per ClassLoader atau AppDomain atau utas, tetapi itu di samping intinya.

Mehrdad Afshari
sumber
5
Di .NET, Anda juga dapat memodifikasi perilaku ini menggunakan atribut [ThreadStatic] - yang membuat statis lokal ke utas tertentu.
TheSoftwareJedi
4
Saya tahu ini adalah postingan lama tetapi bagi pemula seperti saya ini mungkin bermanfaat. stackoverflow.com/questions/7026507/…
user3526905
Tidakkah Anda tidak dapat mengakses instance.instanceField karena ini adalah var pribadi? Atau apakah ini valid karena Anda membuat objek di dalam kelasnya sendiri? Kedengarannya seperti mimpi buruk rekursif bagi saya tapi saya seorang pemula Java.
Matt Corby
Jika anggota statis suatu kelas direferensikan oleh 2 utas yang berbeda maka berapa banyak contoh yang ada dari anggota statis itu? Saya merasa seperti 2 tetapi jika Anda ingin contoh yang sama di utas maka kata kunci yang mudah menguap harus digunakan. Apakah itu benar?
Dan
..dan apakah nilai dipertahankan jika tidak ada instance kelas yang tersisa?
mckenzm
130

Ini berarti bahwa hanya ada satu instance dari "jam" di Hello, tidak satu per setiap instance terpisah dari kelas "Hello", atau lebih-lebih, itu berarti bahwa akan ada satu referensi "jam" yang umum dibagikan di antara semua contoh kelas "Halo".

Jadi jika Anda melakukan "Halo baru" di mana saja dalam kode Anda: A- dalam skenario pertama (sebelum perubahan, tanpa menggunakan "statis"), itu akan membuat jam baru setiap kali "Halo baru" dipanggil, tetapi B- dalam skenario kedua (setelah perubahan, menggunakan "statis"), setiap instance "Halo baru" masih akan berbagi dan menggunakan referensi "jam" awal dan yang sama yang pertama kali dibuat.

Kecuali jika Anda membutuhkan "jam" di suatu tempat di luar main, ini juga akan berfungsi:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}
Paul Tomblin
sumber
Ini adalah cara yang lebih umum untuk melakukannya. The main()rutin harus mandiri.
Jason S
1
Dalam instance kedua itu akan membuat instance baru Clock setiap kali metode utama dipanggil, kan?
Klik Upvote
2
Dalam contoh kedua, clock static, itu hanya akan membuatnya sekali. Dalam contoh saya, di mana jam berada di dalam main, maka ya, itu akan membuatnya baru setiap kali main dipanggil. Tetapi biasanya main hanya dipanggil satu kali saat program mulai, dan ketika keluar, semuanya bebas-ed.
Paul Tomblin
Saya tidak mengerti bagaimana mungkin membuat jam baru di metode utama? seperti yang Anda katakan itu akan membuatnya baru setiap kali main dipanggil, tetapi hanya ada satu metode utama. bagaimana metode utama itu dapat merujuk ke instance jam yang berbeda? Agak sulit untuk memahami bagaimana mungkin untuk membuat instance baru dari jam di main dan menggunakan metode itu sayTime (), tetapi tidak mungkin untuk membuat instance dari utama dan menggunakan sayTime (). bagaimana semuanya gratis ketika main dipanggil satu kali? @PaulTomblin
ShakibaZar
@ user5621266 Saya hanya menggunakan mainmetode karena OP lakukan. Jika sebaliknya itu adalah metode publik yang dipanggil dari tempat lain, dan kelas Hello dipakai lebih dari satu kali, maka itu bisa membuat instance Clock untuk setiap instance Hello, kecuali jika clockstatis.
Paul Tomblin
97

Kata statickunci berarti bahwa sesuatu (bidang, metode, atau kelas bertingkat) terkait dengan tipe daripada setiap instance tipe tertentu. Jadi misalnya, seseorang memanggil Math.sin(...)tanpa instance Mathkelas apa pun, dan memang Anda tidak dapat membuat instance Mathkelas.

Untuk informasi lebih lanjut, lihat bit yang relevan dari Tutorial Java Oracle .


Sidenote

Sayangnya Java memungkinkan Anda untuk mengakses anggota statis seolah-olah mereka adalah anggota contoh, mis

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

Itu membuatnya tampak seolah-olah sleepadalah metode instan, tapi itu sebenarnya metode statis - selalu membuat thread saat ini tidur. Ini praktik yang lebih baik untuk memperjelas ini dalam kode panggilan:

// Clearer
Thread.sleep(5000);
Jon Skeet
sumber
1
Contoh lain: System.out.println () terlihat seperti metode kelas, tetapi sebenarnya metode instan. Karena keluar adalah contoh PrintStream di kelas Sistem.
Jiahui Zhang
@LeslieCheung: Tidak, itu tidak terlihat seperti metode kelas bagi saya, karena System.outtidak suka nama jenis bagi saya.
Jon Skeet
42

Kata statickunci dalam Java berarti bahwa variabel atau fungsi dibagi di antara semua instance kelas itu karena itu termasuk tipe , bukan objek aktual itu sendiri.

Jadi jika Anda memiliki variabel: private static int i = 0;dan Anda menambahkannya ( i++) dalam satu contoh, perubahan akan tercermin dalam semua contoh. isekarang akan menjadi 1 dalam semua kasus.

Metode statis dapat digunakan tanpa membuat instance objek.

geowa4
sumber
4
"Bersama antara semua contoh" memberikan kesan yang salah, IMO - itu menunjukkan bahwa Anda lakukan perlu memiliki sebuah instance dari objek.
Jon Skeet
1
(Padahal benar-benar ada tidak perlu setiap kasus, karena bidang statis dll milik tipe .)
Jon Skeet
@ Jon Skeet statis milik tipe, bukan objek? Bisakah Anda memberi tahu lebih detail? Ketik datatype: int, double, ...?
truongnm
@truongnm: Ketikkan seperti dalam kelas yang mendeklarasikan variabel / metode.
Jon Skeet
26

Penggunaan dasar anggota statis ...

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
}

Itulah cara Anda dapat memiliki nilai yang dibagikan di semua anggota kelas tanpa mengirim instance kelas Halo ke kelas lain. Dan sedikit statis Anda tidak perlu membuat instance kelas.

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

Anda bisa memanggil nilai atau metode statis dengan nama kelas:

Hello.staticValue = "abc";
Vasil Valchev
sumber
22

Statis berarti bahwa Anda tidak harus membuat turunan kelas untuk menggunakan metode atau variabel yang terkait dengan kelas. Dalam contoh Anda, Anda dapat menghubungi:

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

secara langsung, alih-alih:

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

Dari dalam metode statis (yang termasuk kelas) Anda tidak dapat mengakses anggota mana pun yang tidak statis, karena nilainya tergantung pada instantiasi Anda dari kelas. Objek Clock non-statis, yang merupakan anggota instance, akan memiliki nilai / referensi yang berbeda untuk setiap instance kelas Hello Anda, dan karenanya Anda tidak dapat mengaksesnya dari bagian statis kelas.

Elie
sumber
Penjelasan Hebat untuk Konteks Statik :)
Abdel-Raouf
20

Statis di Jawa:

Statis adalah Pengubah Akses Non. Kata kunci statis milik kelas daripada instance kelas. dapat digunakan untuk melampirkan Variabel atau Metode ke Kelas.

Kata kunci statis BISA digunakan dengan:

metode

Variabel

Kelas bersarang di dalam Kelas lain

Blok Inisialisasi

TIDAK BISA digunakan dengan:

Kelas (tidak bersarang)

Konstruktor

Antarmuka

Metode Kelas Batin Lokal (Perbedaan lalu kelas bersarang)

Metode Kelas Batin

Variabel Instance

Variabel Lokal

Contoh:

Bayangkan contoh berikut yang memiliki jumlah instance bernama variabel yang ditambahkan dalam konstruktor:

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

    }
}

Keluaran:

1 1 1

Karena variabel instan mendapatkan memori pada saat pembuatan objek, masing-masing objek akan memiliki salinan variabel instan, jika ditambahkan, itu tidak akan mencerminkan ke objek lain.

Sekarang jika kita mengubah jumlah variabel instance menjadi yang statis maka program akan menghasilkan output yang berbeda:

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

    }
}

Keluaran:

1 2 3

Dalam hal ini variabel statis akan mendapatkan memori hanya sekali, jika ada objek yang mengubah nilai variabel statis, ia akan mempertahankan nilainya.

Statis dengan Final:

Variabel global yang dinyatakan sebagai final dan statis tetap tidak berubah untuk seluruh eksekusi. Karena, anggota statis disimpan dalam memori kelas dan mereka dimuat hanya sekali dalam seluruh eksekusi. Mereka umum untuk semua objek kelas. Jika Anda mendeklarasikan variabel statis sebagai final, salah satu objek tidak dapat mengubah nilainya karena final. Oleh karena itu, variabel yang dinyatakan sebagai final dan statis kadang-kadang disebut sebagai Konstanta. Semua bidang antarmuka disebut konstanta, karena bersifat final dan statis secara default.

masukkan deskripsi gambar di sini

Sumber Daya Gambar: Final Static

Affy
sumber
15

Untuk menambah jawaban yang ada, izinkan saya mencoba dengan gambar:

Tingkat bunga 2% diterapkan untuk SEMUA rekening tabungan. Karena itu statis .

Keseimbangan harus individual , jadi tidak statis.

masukkan deskripsi gambar di sini

Andrejs
sumber
13

Diskusi ini sejauh ini mengabaikan pertimbangan classloader. Sebenarnya, bidang statis Java dibagi antara semua instance kelas untuk classloader yang diberikan .

Julien Chastang
sumber
1
Ini disebutkan oleh Apocalisp dalam komentar tentang jawaban Merhdad.
Zach Langley
1
Poin yang bagus. Banyak orang tidak mengetahui hal ini, tetapi begitu Anda mulai mengacaukan classloader, itu menjadi sangat penting.
sleske
2
Ini semua benar tetapi tidak menjawab pertanyaan. Seharusnya diposting sebagai komentar.
Marquis of Lorne
7

Bidang dapat ditugaskan ke kelas atau instance kelas. Secara default, field adalah variabel instan. Dengan menggunakan staticbidang menjadi variabel kelas, dengan demikian ada satu dan hanya satu clock. Jika Anda membuat perubahan di satu tempat, itu terlihat di mana-mana. Instans varables diubah secara independen satu sama lain.

merah muda
sumber
6

Kata kunci staticdigunakan untuk menunjukkan bidang atau metode sebagai milik kelas itu sendiri dan bukan turunannya. Menggunakan kode Anda, jika objek Clockstatis, semua instance Hellokelas akan berbagi Clockanggota data (bidang) ini secara umum. Jika Anda membuatnya non-statis, setiap instance individu Hellodapat memiliki Clockbidang unik .

Masalahnya adalah Anda menambahkan metode utama ke kelas Anda Hellosehingga Anda bisa menjalankan kode. Masalahnya di sini adalah bahwa metode utama adalah statis dan karena itu, tidak dapat merujuk ke bidang atau metode non-statis di dalamnya. Anda dapat menyelesaikan ini dengan dua cara:

  1. Buat semua bidang dan metode Hellostatis kelas sehingga mereka dapat dirujuk di dalam metode utama . Ini benar-benar bukan hal yang baik untuk dilakukan (atau alasan yang salah untuk membuat bidang dan / atau metode statis)
  2. Buat instance Hellokelas Anda di dalam metode utama dan akses semua bidang itu dan metode seperti yang dimaksudkan di tempat pertama.

Bagi Anda, ini berarti perubahan berikut pada kode Anda:

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

Di Jawa, statickata kunci dapat dianggap sebagai menunjukkan hal-hal berikut:

"Tanpa memperhatikan atau berhubungan dengan contoh khusus"

Jika Anda berpikir staticseperti ini, akan lebih mudah untuk memahami penggunaannya dalam berbagai konteks yang dihadapi:

  • Sebuah staticlapangan adalah bidang yang termasuk kelas daripada keadaan apa pun

  • Sebuah staticmetode adalah metode yang tidak memiliki gagasan this; itu didefinisikan pada kelas dan tidak tahu tentang contoh tertentu dari kelas itu kecuali referensi dilewatkan ke sana

  • Kelas staticanggota adalah kelas bersarang tanpa gagasan atau pengetahuan tentang instance kelas melampirkan (kecuali referensi ke instance kelas melampirkan diteruskan ke sana)

scottb
sumber
5

Statis menjadikan anggota jam sebagai anggota kelas, bukan anggota contoh. Tanpa kata kunci statis, Anda harus membuat turunan dari kelas Hello (yang memiliki variabel anggota jam) - mis

Hello hello = new Hello();
hello.clock.sayTime();
Stephen Doyle
sumber
5

metode statis tidak menggunakan variabel instan dari kelas mereka didefinisikan. Penjelasan yang sangat baik tentang perbedaan dapat ditemukan di halaman ini

Marc Novakowski
sumber
5

Saya telah mengembangkan kesukaan untuk metode statis (hanya, jika mungkin) di kelas "pembantu".

Kelas panggilan tidak perlu membuat variabel anggota lain (contoh) dari kelas pembantu. Anda cukup memanggil metode kelas pembantu. Juga kelas helper ditingkatkan karena Anda tidak lagi memerlukan konstruktor, dan Anda tidak perlu variabel anggota (contoh).

Mungkin ada keuntungan lain.

javaguy
sumber
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
    }
}
Mohammad Parvez
sumber
3

Bisa juga memikirkan anggota statis tidak memiliki pointer "ini". Mereka dibagikan di antara semua contoh.

kal
sumber
3

Memahami konsep statis

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 */

    }
}

Kelas kedua

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

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

main() adalah metode statis yang memiliki dua batasan mendasar:

  1. Metode statis tidak dapat menggunakan anggota data non-statis atau langsung memanggil metode non-statis.
  2. this()dan super()tidak dapat digunakan dalam konteks statis.

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

Output: Kompilasi Waktu Kesalahan

Bharthan
sumber
1

Variabel Statis Hanya dapat diakses hanya dengan metode statis, jadi ketika kita mendeklarasikan variabel statis, metode pengambil dan penyetel akan berupa metode statis

metode statis adalah tingkat kelas yang dapat kita akses menggunakan nama kelas

Berikut ini adalah contoh untuk Variabel Statis Getters And Setters:

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

}
Bala Krishna
sumber
1

Sebuah pertanyaan diajukan di sini tentang pilihan kata 'statis' untuk konsep ini. Itu bohong dengan pertanyaan ini, tapi saya tidak berpikir etimologinya sudah jelas diatasi. Begitu...


Itu karena penggunaan kembali kata kunci, dimulai dengan C.

Pertimbangkan deklarasi data dalam C (di dalam fungsi tubuh):

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

Variabel foo dibuat pada stack ketika fungsi dimasukkan (dan dimusnahkan ketika fungsi berakhir). Sebaliknya, bilah selalu ada, jadi 'statis' dalam arti bahasa Inggris yang umum - bilah tidak ada kemana-mana.

Java, dan bahasa-bahasa serupa, memiliki konsep yang sama untuk data. Data dapat dialokasikan per instance kelas (per objek) atau sekali untuk seluruh kelas. Karena Java bertujuan untuk memiliki sintaks yang akrab untuk programmer C / C ++, kata kunci 'statis' sesuai di sini.

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

Terakhir, kami sampai pada metode.

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

Secara konseptual, ada turunan foo () untuk setiap turunan kelas C. Hanya ada satu turunan bar () untuk seluruh kelas C. Ini paralel dengan kasus yang kita bahas untuk data, dan oleh karena itu menggunakan 'statis Lagi-lagi merupakan pilihan yang masuk akal, terutama jika Anda tidak ingin menambahkan lebih banyak kata kunci yang dilindungi undang-undang ke bahasa Anda.

pengguna13068046
sumber