Kapan saya harus menggunakan "ini" di kelas?


269

Saya tahu itu thismerujuk ke objek saat ini. Tapi saya tidak tahu kapan saya benar-benar perlu menggunakannya. Misalnya, apakah akan ada perbedaan jika saya menggunakan xalih-alih this.xdalam beberapa metode? Mungkin xakan merujuk ke variabel yang lokal untuk metode yang dipertimbangkan? Maksud saya variabel yang terlihat hanya dalam metode ini.

Bagaimana dengan this.method()? Bisakah saya menggunakannya? Haruskah saya menggunakannya. Jika saya hanya menggunakan method(), bukankah itu, secara default, akan diterapkan ke objek saat ini?

Jawaban:


349

Kata thiskunci terutama digunakan dalam tiga situasi. Yang pertama dan paling umum adalah dalam metode setter untuk mendisambiguasi referensi variabel. Yang kedua adalah ketika ada kebutuhan untuk melewatkan instance kelas saat ini sebagai argumen ke metode objek lain. Yang ketiga adalah sebagai cara untuk memanggil konstruktor alternatif dari dalam konstruktor.

Kasus 1: Menggunakan thisuntuk mendamaikan referensi variabel. Dalam metode Java setter, kita biasanya meneruskan argumen dengan nama yang sama dengan variabel anggota pribadi yang kita coba atur. Kami kemudian menetapkan argumen xuntuk this.x. Ini memperjelas bahwa Anda menetapkan nilai parameter "nama" ke variabel "nama" contoh.

public class Foo
{
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

Kasus 2: Menggunakan thissebagai argumen yang diteruskan ke objek lain.

public class Foo
{
    public String useBarMethod() {
        Bar theBar = new Bar();
        return theBar.barMethod(this);
    }

    public String getName() {
        return "Foo";
    }
}

public class Bar
{
    public void barMethod(Foo obj) {
        obj.getName();
    }
}

Kasus 3: Menggunakan thisuntuk memanggil konstruktor alternatif. Dalam komentar, trinithis dengan benar menunjukkan penggunaan umum lain dari this. Ketika Anda memiliki beberapa konstruktor untuk satu kelas, Anda dapat menggunakan this(arg0, arg1, ...)untuk memanggil konstruktor lain yang Anda pilih, asalkan Anda melakukannya di baris pertama konstruktor Anda.

class Foo
{
    public Foo() {
        this("Some default value for bar");

        //optional other lines
    }

    public Foo(String bar) {
        // Do something with bar
    }
}

Saya juga telah melihat thisdigunakan untuk menekankan fakta bahwa variabel instance sedang direferensikan (tanpa perlunya disambiguasi), tetapi itu adalah kasus yang jarang menurut saya.


21
+1 Untuk menyebutkan bahwa Anda juga bisa meneruskan ini sebagai argumen. ini tidak hanya digunakan untuk disambiguasi ruang lingkup.
Alex Jasmin

12
Tentu saja ada juga this(arg1, arg2, ...)di dalam konstruktor.
Thomas Eding

12
@Hiorior: Saya cenderung menulis jawaban singkat dan kemudian menambahkannya dari waktu ke waktu. Terkadang itu tumpang tindih dengan jawaban orang lain, kadang tidak. Dalam kasus edit terakhir saya, trinithis menunjukkan penggunaan umum lainnya thisyang saya lupa, jadi saya menambahkannya ke jawaban saya. Saya tidak melihat ada yang salah dengan ini karena hasil akhirnya adalah jawaban yang lebih baik secara keseluruhan, yang merupakan tujuan dari SO. Saya juga mencoba memberikan kredit sedapat mungkin, seperti yang saya lakukan dalam kasus trinithis.
William Brendel

4
Anda memiliki contoh untuk kasus 1 dan 3. Bisakah Anda memberikan contoh kasus 2 di mana instance kelas saat ini digunakan sebagai argumen untuk metode kelas lain?
dbconfession

4
@ AStar Di sebagian besar basis kode Java yang telah saya thisgunakan selama bertahun-tahun, hanya digunakan jika disambiguasi benar-benar diperlukan, seperti pada contoh setter saya di atas. Gaya pengkodean dan "praktik terbaik" dapat sangat bervariasi tergantung pada siapa yang Anda tanyakan, tentu saja, tetapi secara umum, saya sarankan memilih pola yang masuk akal dan berpegang teguh pada mereka. Konsistensi, bahkan hanya secara internal dalam basis kode tunggal, berjalan jauh menuju keterbacaan dan pemeliharaan.
William Brendel

71

Penggunaan penting kedua this(selain bersembunyi dengan variabel lokal seperti yang sudah dijawab oleh banyak jawaban) adalah ketika mengakses instance luar dari kelas non-statis bersarang:

public class Outer {
  protected int a;

  public class Inner {
    protected int a;

    public int foo(){
      return Outer.this.a;
    }

    public Outer getOuter(){
      return Outer.this;
    }
  }
}

46

Anda hanya perlu menggunakan this- dan kebanyakan orang hanya menggunakannya - ketika ada variabel lokal yang tumpang tindih dengan nama yang sama. (Metode penyetel, misalnya.)

Tentu saja, alasan lain yang baik untuk digunakan thisadalah bahwa hal itu menyebabkan intellisense untuk muncul di IDE :)


1
Tapi kemudian Anda harus mundur ruang setelah Anda mencarinya. Pemrograman melelahkan!
LegendLength

25

Satu-satunya kebutuhan untuk menggunakan this.kualifikasi adalah ketika variabel lain dalam lingkup saat ini berbagi nama yang sama dan Anda ingin merujuk ke anggota contoh (seperti yang dijelaskan William). Selain itu, tidak ada perbedaan perilaku antara xdan this.x.


3
Dan jika Anda memiliki nama duplikat, salah satu variabel Anda harus diganti namanya karena hampir pasti namanya tidak benar. Atau paling tidak, bisa dinamai lebih baik.
CaffGeek

3
@Chad: Ini praktik umum dalam metode Java setter. Namun, di luar metode penyetel, pernyataan Anda biasanya berlaku.
William Brendel

2
Anda mungkin ingin menggunakan this.xuntuk membuat kode Anda membaca sedikit lebih jelas juga, pemeliharaan / keterbacaan kode juga merupakan faktor yang harus Anda pertimbangkan ...
Bryan Rehbein

1
@Chad: Saya tidak cukup setuju. Ya Tuhan, hanya karena "ini." memungkinkan Anda untuk memberikan dua variabel berbeda nama yang sama, mengapa Anda INGIN
BlairHippo

2
@ Blair: Membaca jawaban Anda menjelaskan bahwa Anda tidak memilih praktik ini dalam metode penyetel, tetapi banyak orang yang melakukannya (saya akan memasukkan diri saya dalam daftar itu). Jika saya memiliki metode penyetel yang mengambil nilai, jelas nilai yang diteruskan adalah nilai "baru", jadi menambahkan "baru" ke nama variabel tampaknya menambah redundansi yang tidak perlu ke API publik.
Adam Robinson

15

"ini" juga berguna saat memanggil satu konstruktor dari yang lain:

public class MyClass {
    public MyClass(String foo) {
        this(foo, null);
    }
    public MyClass(String foo, String bar) {
        ...
    }
}

11

this berguna dalam pola pembangun.

public class User {

    private String firstName;
    private String surname;

    public User(Builder builder){
        firstName = builder.firstName;
        surname = builder.surname;
    }

    public String getFirstName(){
        return firstName;
    }

    public String getSurname(){
        return surname;
    }

    public static class Builder {
        private String firstName;
        private String surname;

        public Builder setFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder setSurname(String surname) {
            this.surname = surname;
            return this;
        }

        public User build(){
            return new User(this);
        }

    }

    public static void main(String[] args) {
        User.Builder builder = new User.Builder();
        User user = builder.setFirstName("John").setSurname("Doe").build();
    }

}

1
Ini adalah jenis jawaban yang saya inginkan ketika saya mencari dan berakhir di sini, tetapi Anda tidak memiliki penjelasan tentang kode Anda, jadi kebanyakan orang yang bertanya tentang "ini", tidak akan mengerti apa yang "mengembalikan pengguna baru (ini);" berarti, karena saya tidak ...
nckbrz

Pola Builder digunakan untuk menentukan parameter dengan jelas pada konstruksi. Alih-alih memiliki Pengguna baru (string, string) tanpa cara mudah untuk mengetahui mana string yang mana, Anda akan memiliki Builder baru (). SetFirstName ("Jane"). SetSurname ("Smith"). Build (). Anda mengembalikan ini dari fungsi Builder.set ... () sehingga Anda dapat rantai mereka.
ChrisPhoenix

10

Ada banyak jawaban bagus, tetapi ada alasan lain yang sangat kecil untuk diletakkan di thismana - mana. Jika Anda telah mencoba membuka kode sumber Anda dari editor teks biasa (mis. Notepad dll), menggunakan thisakan membuatnya jauh lebih jelas untuk dibaca.

Bayangkan ini:

public class Hello {
    private String foo;

    // Some 10k lines of codes

    private String getStringFromSomewhere() {
        // ....
    }

    // More codes

    public class World {
        private String bar;

        // Another 10k lines of codes

        public void doSomething() {
            // More codes
            foo = "FOO";
            // More codes
            String s = getStringFromSomewhere();
            // More codes
            bar = s;
        }
    }
}

Ini sangat jelas untuk dibaca dengan IDE modern, tetapi ini akan menjadi mimpi buruk total untuk dibaca dengan editor teks biasa.

Anda akan berjuang untuk mencari tahu di mana fooberada, sampai Anda menggunakan fungsi "menemukan" editor. Maka Anda akan berteriak getStringFromSomewhere()karena alasan yang sama. Terakhir, setelah Anda lupa apa yang sada, itu bar = sakan memberi Anda pukulan terakhir.

Bandingkan dengan ini:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. Anda tahu fooadalah variabel yang dideklarasikan di kelas luar Hello.
  2. Anda tahu getStringFromSomewhere()adalah metode yang dideklarasikan di kelas luar juga.
  3. Anda tahu bahwa itu barmilik Worldkelas, dan smerupakan variabel lokal yang dideklarasikan dalam metode itu.

Tentu saja, setiap kali Anda mendesain sesuatu, Anda membuat aturan. Jadi saat merancang API atau proyek Anda, jika aturan Anda termasuk "jika seseorang membuka semua kode sumber ini dengan notepad, ia harus menembak dirinya sendiri di kepala," maka Anda benar-benar baik-baik saja untuk tidak melakukan ini .


jawaban bagus @Jai
gaurav

Alasan pertama untuk menembak adalah menulis kelas dengan beberapa baris kode
10rb

@LuCio Lol true xD
Jai

7

Kecuali Anda memiliki nama variabel yang tumpang tindih, itu hanya untuk kejelasan ketika Anda membaca kode.


1
Ketika Anda melihat thiskata kunci terus-menerus ketika itu tidak perlu itu hanya kode boilerplate membuat kode lebih sulit untuk dibaca.
AxeEffect

Saya baru saja menemukan proyek open source yang menuntut semua anggota diawali dengan 'ini'. Terlepas dari itu, proyek ini ditulis dengan sangat baik tetapi saya tergoda untuk terlibat dalam perdebatan agama dengan mereka.
LegendLength

4
@Aeffect Saya tahu ini benar-benar tua tapi ... thisTIDAK membuat kode lebih sulit untuk dibaca lmao.
Xatenev

4

@William Brendel menjawab dengan tiga kasus penggunaan yang berbeda dengan cara yang baik.

Gunakan case 1:

Halaman dokumentasi java resmi pada ini menyediakan kasus penggunaan yang sama.

Dalam metode instance atau konstruktor, ini adalah referensi ke objek saat ini - objek yang disebut metode atau konstruktornya. Anda bisa merujuk ke anggota objek saat ini dari dalam metode instance atau konstruktor dengan menggunakan ini.

Ini mencakup dua contoh:

Menggunakan ini dengan Field dan Menggunakan ini dengan Konstruktor

Gunakan case 2:

Use case lain yang belum dikutip dalam posting ini: thisdapat digunakan untuk menyinkronkan objek saat ini dalam aplikasi multi-threaded untuk menjaga bagian penting dari data & metode.

synchronized(this){
    // Do some thing. 
}

Gunakan case 3:

Implementasi pola Builder tergantung pada penggunaan thisuntuk mengembalikan objek yang dimodifikasi.

Lihat posting ini

Menjaga pembangun di kelas terpisah (antarmuka lancar)


2

Google membuka halaman di situs Sun yang membahas ini sedikit.

Anda benar tentang variabel; thismemang bisa digunakan untuk membedakan variabel metode dari bidang kelas.

    private int x;
    public void setX(int x) {
        this.x=x;
    }

Namun, saya sangat membenci konvensi itu. Memberi dua variabel berbeda nama yang sama persis adalah resep untuk bug. Saya lebih suka sesuatu seperti:

    private int x;
    public void setX(int newX) {
        x=newX;
    }

Hasil yang sama, tetapi tanpa kemungkinan bug di mana Anda secara tidak sengaja merujuk xketika Anda benar-benar dimaksudkan untuk merujuk x.

Untuk menggunakannya dengan metode, Anda benar tentang efeknya; Anda akan mendapatkan hasil yang sama dengan atau tanpa itu. Bisakah kamu menggunakannya? Tentu. Haruskah Anda menggunakannya? Terserah Anda, tetapi mengingat bahwa saya secara pribadi berpikir itu verbositas yang tidak berarti yang tidak menambah kejelasan (kecuali kode dijejali pernyataan impor statis), saya tidak cenderung menggunakannya sendiri.


4
Ini bukan konvensi, ini adalah mekanisme pelingkupan bahasa program. Apa yang Anda daftarkan - menggunakan newX (saya lebih suka pX untuk parameter x) adalah sebuah konvensi.
Bill K

@ Bill K: Saya tidak mengerti perbedaan yang Anda buat. Saya dapat memilih untuk memberi nama variabel input x, atau newX, atau pX, atau mangroveThroatWarblerX. Bagaimana memilih untuk memberikannya nama yang identik dengan variabel yang disetel BUKAN konvensi, sambil menambahkan "baru" atau "p" atau "Gratuitous Monty Python Referensi" ADALAH konvensi?
BlairHippo

3
"Referensi Gratuitoud Monty Python" bukan sebuah konvensi, ini adalah HUKUM.
Adam Robinson

+1: Kami menggunakan standar penamaan yang berbeda untuk argumen dan variabel metode dari itu untuk variabel kelas karena alasan ini. Kami menyingkat argumen / metode vars dan menggunakan kata-kata penuh untuk variabel kelas / instance.
Lawrence Dol

1
Memecahkannya dengan menggunakan konvensi penamaan adalah, hmm, konvensi. Memecahkannya dengan menggunakan fitur bahasa - Saya kira memilih untuk tidak pernah menggunakan fitur bahasa itu atau selalu menggunakannya akan menjadi konvensi ... Menggunakan ini. untuk setiap kali Anda mengakses anggota akan menjadi konvensi. Kurasa tidak masalah, aku benci. Ini juga.
Bill K


1

ketika ada dua variabel satu variabel instan dan variabel lokal lainnya dari nama yang sama maka kita menggunakan ini. untuk merujuk objek yang sedang dieksekusi saat ini untuk menghindari konflik antara nama.


1

thisadalah referensi ke objek saat ini. Ini digunakan dalam konstruktor untuk membedakan antara variabel kelas lokal dan saat ini yang memiliki nama yang sama. misalnya:

public class circle {
    int x;
    circle(int x){
        this.x =x;
        //class variable =local variable 
    }
} 

thisjuga dapat digunakan untuk memanggil satu konstruktor dari konstruktor lain. misalnya:

public class circle {
    int x;

    circle() { 
        this(1);
    }

    circle(int x) {
        this.x = x; 
    }
}

0

Akankah ada perbedaan jika saya menggunakan "x" alih-alih "this.x" dalam beberapa metode?

Biasanya tidak. Tapi kadang-kadang ada bedanya:

  class A {
     private int i;
     public A(int i) {
        this.i = i; // this.i can be used to disambiguate the i being referred to
     }
  }

Jika saya hanya menggunakan "metode ()", apakah itu tidak akan, secara default, diterapkan ke objek saat ini?

Iya. Tetapi jika perlu, this.method()jelaskan bahwa panggilan itu dilakukan oleh objek ini.


0

thistidak mempengaruhi kode yang dihasilkan - ini adalah waktu kompilasi operator dan kode yang dihasilkan dengan atau tanpa itu akan sama. Ketika Anda harus menggunakannya, tergantung pada konteksnya. Misalnya Anda harus menggunakannya, seperti yang Anda katakan, ketika Anda memiliki variabel lokal yang membayangi variabel kelas dan Anda ingin merujuk ke variabel kelas dan bukan variabel lokal.

sunting: dengan "kode yang dihasilkan akan sama" Maksud saya tentu saja, ketika beberapa variabel dalam lingkup lokal tidak menyembunyikan yang milik kelas. Jadi

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

   public void thisModify() {
      this.i = 9;
   }
}

kode yang dihasilkan dari kedua metode akan sama. Perbedaannya adalah jika beberapa metode mendeklarasikan variabel lokal dengan nama yang sama

  public void m() {
      int i;
      i = 9;  // i refers to variable in method's scope
      this.i = 9; // i refers to class variable
  }

0

Sehubungan dengan posting William Brendel dan pertanyaan dbconfessions , mengenai kasus 2 . Berikut ini sebuah contoh:

public class Window {

  private Window parent;

  public Window (Window parent) {
    this.parent = parent;
  }

  public void addSubWindow() {
    Window child = new Window(this);
    list.add(child);
  }

  public void printInfo() {
    if (parent == null) {
      System.out.println("root");
    } else {
      System.out.println("child");
    }
  }

}

Saya pernah melihat ini digunakan, ketika membangun hubungan orangtua-anak dengan objek. Namun, harap dicatat bahwa ini disederhanakan demi singkatnya.


0

Kata kunci "Ini" dalam java digunakan untuk merujuk objek kelas saat ini.

Ada 6 penggunaan kata kunci "ini" di java

  1. Mengakses variabel level kelas : kebanyakan digunakan jika variabel level lokal dan kelas sama
  2. Mengakses metode kelas : ini adalah perilaku default dan dapat diabaikan
  3. Untuk memanggil konstruktor lain dari kelas yang sama
  4. Menggunakan kata kunci 'ini' sebagai nilai balik : untuk mengembalikan instance saat ini dari metode
  5. Melewati kata kunci 'ini' sebagai argumen ke metode Melewati: untuk melewatkan instance kelas saat ini sebagai argumen
  6. kata kunci ini sebagai argumen untuk konstruktor : untuk melewatkan instance kelas saat ini sebagai argumen

ref: https://stacktraceguru.com/java/this-keyword-in-java


-8

Untuk memastikan bahwa anggota objek saat ini digunakan. Kasus di mana keselamatan ulir menjadi perhatian, beberapa aplikasi dapat mengubah nilai anggota objek yang salah, untuk alasan ini ini harus diterapkan pada anggota sehingga nilai anggota objek yang benar digunakan.

Jika objek Anda tidak mementingkan keamanan utas, maka tidak ada alasan untuk menentukan nilai anggota objek mana yang digunakan.


Ini sebenarnya bukan masalahnya. Saya bahkan tidak yakin kasus apa yang Anda pikirkan, tetapi sebuah contoh mungkin membantu untuk memahami apa yang Anda coba katakan.
David Berger

1
Iya. Saya tahu apa yang Anda jelaskan melibatkan keamanan utas. Tidak ada jawaban yang benar untuk pertanyaan ini yang melibatkan keamanan utas. Jika "ini" diperlukan untuk merujuk ke objek yang benar, maka setelah itu melakukannya, metode atau atribut akan menjadi aman jika dan hanya jika itu disinkronkan. Jika referensi sama sekali ambigu, itu akan menjadi ambigu apakah multi-threading merupakan masalah.
David Berger
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.