Bir sınıfta ne zaman “bunu” kullanmalıyım?


267

Bunun thismevcut bir nesneyi ifade ettiğini biliyorum . Ama gerçekten ne zaman kullanmam gerektiğini bilmiyorum. Örneğin, bazı yöntemlerde kullanmak xyerine herhangi bir fark olacak this.xmı? Olabilir xdikkate alınan yöntem için yerel bir değişkene sevk edecektir? Sadece bu yöntemde görülen değişkeni kastediyorum.

Ne olmuş this.method()? Kullanabilirmiyim? Kullanmalı mıyım? Sadece kullanırsam method(), varsayılan olarak geçerli nesneye uygulanmaz mı?

Yanıtlar:


347

thisAnahtar kelime öncelikle üç durumlarda kullanılır. İlk ve en yaygın değişken değişkenleri belirsizleştirmek için ayarlayıcı yöntemlerde. İkincisi, geçerli sınıf örneğini başka bir nesnenin yöntemine argüman olarak geçirmeye ihtiyaç duyulduğu zamandır. Üçüncüsü, bir kurucu içinden alternatif kurucuları çağırmanın bir yoludur.

Durum 1:this Değişken referansları belirsizleştirmek için kullanma . Java ayarlayıcı yöntemlerinde, genellikle ayarlamaya çalıştığımız özel üye değişkeniyle aynı ada sahip bir bağımsız değişken iletiriz. Sonra argüman atamak xiçin this.x. Bu, "name" parametre değişkenine "name" parametresinin değerini atadığınızı açıkça gösterir.

public class Foo
{
    private String name;

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

Durum 2: Bağımsız thisdeğişken olarak başka bir nesneye geçildi.

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

Durum 3:this Alternatif kurucuları çağırmak için kullanma . Yorumlarda, trinithis başka bir yaygın kullanımı doğru bir şekilde gösterdi this. Tek bir sınıf için birden fazla kurucunuz olduğunda this(arg0, arg1, ...), kurucunuzun ilk satırında bunu yapmanız koşuluyla, seçtiğiniz başka bir kurucuyu çağırmak için kullanabilirsiniz .

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

        //optional other lines
    }

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

Ben de thisbir örnek değişkeni başvurulan (vurgulama ihtiyacını sans) gerçeğini vurgulamak için kullanılan gördüm , ama bu benim görüşüme göre nadir bir durumdur.


21
Ayrıca geçebilir söz için 1 bu bağımsız değişken olarak. bu yalnızca kapsamın netleştirilmesinde kullanılmaz.
Alex Jasmin

12
Tabii ki this(arg1, arg2, ...)bir kurucu da var.
Thomas Eding

12
@Hazior: Kısa bir cevap yazma ve daha sonra cevaplama eğilimindeyim. Bazen bu diğer insanların cevaplarıyla örtüşüyor, bazen değil. Son düzenlememde, trinithis unuttuğum başka bir yaygın kullanıma işaret etti this, bu yüzden cevabımı ekledim. Bunda yanlış bir şey görmüyorum, çünkü sonuç genel olarak daha iyi bir cevaptır, ki bu kesinlikle SO'nun amacıdır. Ayrıca, trinit durumunda olduğu gibi mümkün olan her yerde kredi vermeye çalışıyorum.
William Brendel

4
Durum 1 ve 3 için örnekleriniz var. Lütfen geçerli sınıf örneğinin başka bir sınıfın yöntemi için bağımsız değişken olarak kullanıldığı durum 2'ye bir örnek verebilir misiniz?
dbconfession

4
@AStar Yıllar boyunca üzerinde çalıştığım Java kod tabanlarının çoğunda this, yalnızca yukarıdaki ayarlayıcı örneğimde olduğu gibi, anlam ayrımı gerçekten gerekliyse kullanılır. Kodlama stilleri ve "en iyi uygulamalar", kime sorduğunuza bağlı olarak büyük ölçüde değişebilir, ancak genel olarak, makul kalıpları seçmenizi ve bunlara bağlı kalmanızı öneririm. Tutarlılık, sadece dahili olarak tek bir kod tabanında bile, okunabilirlik ve sürdürülebilirlik için çok yol kat ediyor.
William Brendel

71

İkinci önemli kullanımı this (zaten söylendiği kadar çok yerel bir değişkeni saklamanın yanı sıra) iç içe geçmiş statik olmayan bir sınıftan bir dış örneğe erişmektir:

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

Sadece kullanman gerek this aynı ada sahip çakışan bir yerel değişken olduğunda kullanmanız gerekir - ve çoğu kişi bunu kullanır. (Örneğin, ayarlayıcı yöntemleri.)

Tabii ki, kullanmanın iyi bir nedeni de thisIDE'lerde zekanın ortaya çıkmasına neden olmasıdır :)


1
Ama sonra baktıktan sonra geri almalısınız. Programlama yorucu!
LegendLength

25

Niteleyiciyi kullanmanız gereken tek this.şey, geçerli kapsamdaki başka bir değişkenin aynı adı paylaşması ve örnek üyeye başvurmak istediğinizdir (William'ın açıkladığı gibi). Bunun dışında arasındaki davranış hiçbir fark yoktur xve this.x.


3
Yinelenen adlarınız varsa, değişkenlerinizden biri neredeyse kesinlikle yanlış adlandırıldığı için yeniden adlandırılmalıdır. Ya da en azından daha iyi adlandırılabilir.
CaffGeek

3
@Chad: Java ayarlayıcı yöntemlerinde yaygın olarak kullanılan bir uygulamadır. Ancak, ayarlayıcı yöntemlerin dışında, ifadeleriniz genellikle geçerlidir.
William Brendel

2
this.xKodunuzu biraz daha açık bir şekilde okumak için kullanmak isteyebilirsiniz , kodun sürdürülebilirliği / okunabilirliği de göz önünde bulundurmanız gereken bir faktördür ...
Bryan Rehbein

1
@Chad: Yeterince katılıyorum. Tanrım, sadece "bu" olduğu için. iki farklı değişkene aynı adı vermenizi sağlar, neden İSTEMEK İSTERSİNİZ?
BlairHippo

2
@Blair: Cevabınızı okumak, bu uygulamayı ayarlayıcı yöntemlerde tercih etmediğinizi açıkça gösteriyor, ancak birçok kişi bunu yapıyor (kendimi bu listeye dahil ederim). Bir değer alan bir ayarlayıcı yöntemim varsa, açıkça geçirilen değer "yeni" değer olmaktır, bu nedenle değişken adına "yeni" eklemek, genel API'ya gereksiz yedeklilik eklemek gibi görünüyor.
Adam Robinson

15

"this", bir kurucuyu diğerinden çağırırken de yararlıdır:

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

11

this oluşturucu şablonunda kullanışlıdır.

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
Bu, burada arama yaptığımda ve bitirdiğimde istediğim cevaptı, ancak kodunuzla ilgili bir açıklamanız yok, bu nedenle "bu" ile ilgili soru soran çoğu kişi, "yeni kullanıcı (bu);" demek, ben yok gibi ...
nckbrz

Oluşturucu deseni, yapılarda parametreleri açıkça belirtmek için kullanılır. Hangi dizenin hangisi olduğunu söylemenin kolay bir yolu olmayan yeni Kullanıcıya (string, string) sahip olmak yerine, yeni Builder (). SetFirstName ("Jane"). SetSurname ("Smith"). Build (). Bunu Builder.set ... () işlevlerinden döndürerek zincirleyebilirsiniz.
ChrisPhoenix

10

Çok iyi cevaplar var, ama thisher yere koymak için çok küçük bir neden var. Kaynak kodlarınızı normal bir metin düzenleyicisinden (örn. Not defteri vb.) Açmayı denediyseniz,this okumayı çok daha açık hale getirecektir.

Şunu hayal edin:

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

Bu herhangi bir modern IDE ile okumak için çok açık, ancak bu normal bir metin editörü ile okumak için tam bir kabus olacak.

fooEditörün "find" işlevini kullanana kadar nerede olduğunu bulmak için mücadele edeceksiniz . Sonra çığlık atacaksıngetStringFromSomewhere() aynı sebeple . Son olarak, ne solduğunu unuttuktan sonra ,bar = s size son darbeyi verecektir.

Şununla karşılaştırın:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. Bilirsin foo dış sınıfta bildirilen bir değişkendirHello .
  2. Bilirsin getStringFromSomewhere() yanı dış sınıfta bildirilen bir yöntemdir.
  3. Bunun sınıfa barait olduğunu biliyorsunuz Worldves bu yöntemde bildirilen yerel bir değişken .

Tabii ki, ne zaman bir şey tasarlarsanız, kurallar yaratırsınız. Senin API veya projeyi tasarlarken Yani, senin kuralların eklerseniz yapmak o zaman tamamen iyi değil "Birisi bir not defteri ile tüm bu kaynak kodlarını açarsa, o kendini, kafasından / onu öldürmeliyiz" bu .


Büyük cevap @Jai
gaurav

Çekim yapmanın ilk nedeni, özellikle kod zaten iç içe
geçmesi

@LuCio Lol true xD
Jai

7

Üst üste binen değişken isimleriniz yoksa, kodu okurken anlaşılırlık sağlamak içindir.


1
thisGerekli olmadığında anahtar kelimeyi sürekli gördüğünüzde , kodun okunmasını zorlaştıran ortak koddur.
AxeEffect

Az önce tüm üyelerin 'bu' ön ekini almasını isteyen açık kaynaklı bir projeyle karşılaştım . Bunun dışında proje çok iyi yazılmış ama onlarla dini tartışmalara girmeye cazipim.
LegendLength

4
@AxeEffect Bu gerçekten eski olduğunu biliyorum ama ... thislmao okumak zor kod yapmaz.
Xatenev

4

@William Brendel cevabı üç farklı kullanım durumunu iyi bir şekilde verdi.

Kullanım örneği 1:

Bu konudaki resmi java dokümantasyon sayfası aynı kullanım durumlarını sağlar.

Bir örnek yöntemi veya bir kurucu içinde bu, geçerli nesneye bir başvurudır - yöntemi veya kurucusu çağrılan nesne. Bunu kullanarak, bir örnek yönteminden veya bir kurucudan geçerli nesnenin herhangi bir üyesine başvurabilirsiniz.

İki örneği kapsar:

Bir Cisim ile bu kullanma ve bir Oluşturucu ile bu kullanma

Kullanım örneği 2:

Bu yazıda alıntılanmamış diğer kullanım durumu: thisveri ve yöntemlerin kritik bölümünü korumak için çok iş parçacıklı bir uygulamada mevcut nesneyi senkronize etmek için kullanılabilir.

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

Kullanım örneği 3:

Oluşturucu deseninin uygulanması this, değiştirilen nesneyi döndürmek için kullanımına bağlıdır .

Bu gönderiye bakın

Oluşturucuyu ayrı bir sınıfta tutma (akıcı arayüz)


2

Google, Sun sitesinde bunu biraz tartışan bir sayfa açtı.

Değişken konusunda haklısın; thisaslında bir yöntem değişkenini sınıf alanından ayırmak için kullanılabilir.

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

Ancak bu sözleşmeden gerçekten nefret ediyorum. Kelimenin tam anlamıyla özdeş iki farklı değişken vermek hatalar için bir reçetedir. Ben çok satırlarında bir şey tercih ederim:

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

Aynı sonuçlar, ancak xgerçekten başvurmak istediğinizde yanlışlıkla başvurduğunuz bir hata şansı yokx .

Bir yöntemle kullanmaya gelince, efektler konusunda haklısınız; aynı sonuçları olsun ya da olmasın elde edersiniz. Kullanabilir misin? Elbette. Kullanmalı mısın? Size kalmış, ancak kişisel olarak herhangi bir netlik katmayan anlamsız bir ayrıntı olduğunu düşündüğüm göz önüne alındığında (kod statik ithalat ifadeleriyle dolu olmadığı sürece) kendim kullanmaya meyilli değilim.


4
Bu bir kongre değil, bir program dili kapsam belirleme mekanizması. Listeledikleriniz - newX kullanımı (parametre x için pX'i tercih ederim) bir kuraldır.
Bill K

@ Fatura K: Yaptığın ayrımı anlamıyorum. Giriş değişkenini x veya newX veya pX veya mangroveThroatWarblerX olarak adlandırmayı seçebilirim. "Yeni" ya da "p" ya da "Ödüllü Monty Python Referansları" ARE konvansiyonlarını öne çıkarırken, buna bir kural DEĞİL ayarladığı değişkenle özdeş bir ad vermeyi nasıl seçersiniz?
BlairHippo

3
"Gratuitoud Monty Python Referansları" bir sözleşme değil, LAW.
Adam Robinson

+1: Bu nedenle, bağımsız değişkenler ve yöntem değişkenleri için sınıf değişkenlerinden farklı bir adlandırma standardı kullanırız. Argüman / yöntem değişkenlerini kısaltır ve sınıf / örnek değişkenleri için tam kelimeler kullanırız.
Lawrence Dol

1
Bir adlandırma kuralı kullanarak çözmek, hmm, bir kuraldır. Bir dil özelliğini kullanarak çözme - Sanırım o dil özelliğini asla kullanmamayı veya her zaman kullanmayı bir kural olurdu ... Bunu kullanarak. bir üyeye her eriştiğinizde bir kongre olur. Sanırım çok önemli değil, bundan da nefret ediyorum.
Bill K

2

Java'da 'this' anahtar kelimesini kullanmanın yolları şunlardır:

  1. kullanma thisGeçerli sınıf örneği değişkenlerine başvurmak için anahtar kelime
  2. kullanma this()Geçerli sınıf yapıcısını çağırmak için
  3. thisGeçerli sınıf örneğini döndürmek için anahtar kelime kullanma
  4. thisAnahtar kelimeyi yöntem parametresi olarak kullanma

https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html


1

iki değişken bir örnek değişken ve aynı addaki diğer yerel değişken olduğunda, bunu kullanırız. adlar arasındaki çakışmayı önlemek için geçerli yürütme nesnesine başvurma.


1

thisgeçerli nesneye bir referanstır. Yapıcıda, aynı ada sahip yerel ve geçerli sınıf değişkenini ayırt etmek için kullanılır. Örneğin:

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

thisbir kurucuyu başka bir kurucudan çağırmak için de kullanılabilir. Örneğin:

public class circle {
    int x;

    circle() { 
        this(1);
    }

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

0

Bazı yöntemlerde "this.x" yerine "x" kullanırsam herhangi bir fark olur mu?

Genellikle hayır. Ancak bazen fark yaratır:

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

Sadece "method ()" kullanırsam, varsayılan olarak geçerli nesneye uygulanmaz mı?

Evet. Ancak gerekirse this.method(), çağrının bu nesne tarafından yapıldığını açıklığa kavuşturur.


0

thissonuçta ortaya çıkan kodu etkilemez - derleme zamanı operatörüdür ve onunla birlikte veya onsuz üretilen kod aynı olacaktır. Ne zaman kullanmanız gerektiğine göre, bağlama bağlıdır. Örneğin, dediğin gibi, sınıf değişkenini gölgeleyen yerel değişkeniniz olduğunda ve yerel değişkene değil sınıf değişkenine başvurmak istediğinizde bunu kullanmanız gerekir.

edit: tarafından "sonuç kodu aynı olacak" Tabii ki, yerel kapsamdaki bazı değişken sınıfa ait olanı gizlemek değil demek. Böylece

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

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

her iki yöntemin sonuç kodu aynı olacaktır. Fark, bazı yöntemlerin aynı ada sahip yerel değişkeni bildirmesi

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

0

İle ilgili olarak William Brendel 'ın mesajlar ve dbconfessions ilişkin soruya, söz 2 . İşte bir örnek:

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

}

Bunun, ebeveyn-çocuk ilişkisini nesnelerle oluştururken kullanıldığını gördüm. Bununla birlikte, kısalık adına basitleştirildiğini lütfen unutmayın.


0

Java'daki “This” anahtar sözcüğü, geçerli sınıf nesnelerine başvurmak için kullanılır.

Java'da "this" anahtar kelimesinin 6 kullanımı vardır

  1. Sınıf seviyesi değişkenine erişim : çoğunlukla yerel ve sınıf seviyesi değişkeni aynı ise kullanılır
  2. Sınıf yöntemlerine erişme : bu varsayılan davranıştır ve yok sayılabilir
  3. Diğer kurucuları çağırmak içinAynı sınıftaki
  4. Dönüş değeri olarak 'this' anahtar kelimesini kullanma : geçerli örneği yöntemden döndürmek için
  5. 'This' anahtar sözcüğünü Passing yöntemine bağımsız değişken olarak iletme: geçerli sınıf örneğini bağımsız değişken olarak geçirme
  6. yapıcıya argüman olarak bu anahtar kelime : geçerli sınıf örneğini argüman olarak iletmek için

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


-8

Geçerli nesnenin üyelerinin kullanıldığından emin olmak için. İş parçacığı güvenliğinin önemli olduğu durumlarda, bazı uygulamalar yanlış nesne üye değerlerini değiştirebilir, bu nedenle doğru nesne üye değerinin kullanılması için üyeye uygulanması gerekir.

Nesneniz iş parçacığı güvenliği ile ilgili değilse, hangi nesne üyesinin değerinin kullanılacağını belirtmek için bir neden yoktur.


Aslında durum böyle değil. Hangi vakayı düşündüğünüzden bile emin değilim, ancak bir örnek söylemeye çalıştığınızı anlamaya yardımcı olabilir.
David Berger

1
Evet. Açıkladığınız şeyin iplik güvenliğini içerdiğini biliyorum. Bu soruya iplik güvenliğini içeren doğru bir cevap yoktur. Doğru nesneye başvurmak için "bu" gerekliyse, bunu yaptıktan sonra, yöntem veya öznitelik yalnızca eşitlenmişse güvenli olur. Referans hiç belirsizse, çoklu iş parçacığının sorun olup olmadığı belirsiz olacaktır.
David Berger
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.