java oop教學 - 我應該什麼時候在課堂上使用“this”?





and what (15)


關於William Brendel的帖子和dbconfession問題,關於案例2 。 這裡是一個例子:

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

}

我已經看到了這個用法,當建立與對象的父子關係時。 但請注意,為了簡潔起見,它被簡化了。

我知道this是指一個當前對象。 但我不知道我什麼時候需要使用它。 例如,如果我在某些方法中使用x而不是this.x ,會有什麼區別嗎? 可能是x會引用一個變量,它是所考慮方法的局部變量? 我的意思是只有在這種方法中才能看到的變量。

那麼this.method()呢? 我可以使用它嗎? 我應該使用它。 如果我只是使用method() ,默認情況下它不會應用於當前對象嗎?




當有兩個變量一個實例變量和其他同名的局部變量時,我們使用這個。 引用當前執行對像以避免名稱之間的衝突。




this關鍵字主要用於三種情況。 第一個也是最常見的是setter方法來消除變量引用的歧義。 第二種是當需要將當前類實例作為參數傳遞給另一個對象的方法時。 第三種方法是從構造函數中調用備用構造函數。

案例1:使用this來消除變量引用的歧義。 在Java setter方法中,我們通常傳入一個與我們試圖設置的私有成員變量同名的參數。 然後我們將參數x分配給this.x 這明確表示您將參數“name”的值分配給實例變量“name”。

public class Foo
{
    private String name;

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

情況2: this用作傳遞給另一個對象的參數。

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

案例3:使用this來調用備用構造函數。 在評論中, trinithis正確指出了this另一個常見用法。 當你有一個類的多個構造函數時,你可以使用this(arg0, arg1, ...)來調用你選擇的另一個構造函數,只要你在構造函數的第一行中這樣做。

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

        //optional other lines
    }

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

我也曾經看到過this為了強調一個實例變量被引用的事實(不需要消除歧義),但在我看來這是一種罕見的情況。




this不會影響結果代碼 - 它是編譯時間運算符,並且使用或不使用它生成的代碼都是相同的。 當你必須使用它時,取決於上下文。 例如,您必須使用它,如您所說,當您有局部變量影響類變量並且您想要引用類變量而不是本地變量時。

編輯:通過“結果代碼將是相同的”我的意思,當然,當局部範圍內的某些變量不隱藏屬於類的一個。 從而

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

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

兩種方法的結果代碼都是相同的。 區別在於某些方法聲明了具有相同名稱的局部變量

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



如果我在某些方法中使用“x”而不是“this.x”,會有什麼區別嗎?

通常不會。 但它有時會有所作為:

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

如果我只是使用“method()”,默認情況下它不會應用於當前對象嗎?

是。 但是如果需要的話, this.method()說明這個對this.method()由這個對象調用的。




確保使用當前對象的成員。 在線程安全問題的情況下,某些應用程序可能會更改錯誤的對象成員值,因此應將此應用於成員,以便使用正確的對象成員值。

如果你的對像不關心線程安全性,那麼沒有理由指定使用哪個對象成員的值。




this在構建器模式中很有用。

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

}



this是對當前對象的引用。 它在構造函數中用於區分具有相同名稱的本地類和當前類變量。 例如:

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

this也可以用來從另一個構造函數中調用一個構造函數。 例如:

public class circle {
    int x;

    circle() { 
        this(1);
    }

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



以下是在java中使用'this'關鍵字的方法:

  1. 使用this關鍵字來引用當前類實例變量
  2. 使用this()來調用當前的類構造函數
  3. 使用this關鍵字返回當前類實例
  4. 使用this關鍵字作為方法參數

this




從另一個構造器中調用一個構造器時,“this”也很有用:

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



除非你有重疊的變量名稱,否則當你閱讀代碼時它的確很清晰。




谷歌在Sun網站上發布了一個討論這個問題的頁面。

你對這個變量是正確的。 this確實可以用來區分方法變量和類字段。

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

但是,我真的很討厭那個約定。 給兩個不同的變量字面上相同的名稱是一個錯誤的秘訣。 我更喜歡以下幾點:

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

相同的結果,但沒有機會出現一個錯誤,當你真的想要引用x而不是意外地引用x時。

至於使用它的方法,你是正確的影響; 無論有沒有它,你都會得到相同的結果。 你可以使用它嗎? 當然。 你應該使用它嗎? 由你自己決定,但鑑於我個人認為這是毫無意義的冗長,並沒有增加任何清晰度(除非代碼充滿了靜態導入語句),我並不傾向於自己使用它。




有很多很好的答案,但還有另一個很小的理由把this放在每個地方。 如果你已經嘗試從普通的文本編輯器(例如記事本等)打開你的源代碼,使用this可以使它更清晰地閱讀。

想像一下:

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

使用任何現代化的IDE閱讀都非常清楚,但使用常規文本編輯器閱讀這將是一場完全的噩夢。

在使用編輯器的“查找”功能之前,您將很難找出foo所在的位置。 然後,出於同樣的原因,您將在getStringFromSomewhere()尖叫。 最後,在你忘記了是什麼之後,那個bar = s會給你最後一擊。

比較一下:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. 你知道foo是一個在外部類Hello聲明的變量。
  2. 你知道getStringFromSomewhere()也是一個在外部類中聲明的方法。
  3. 你知道bar屬於World類, s是在該方法中聲明的局部變量。

當然,無論什麼時候設計一些東西,你都會創建規則。 因此,在設計你的API或項目時,如果你的規則包括“如果有人用記事本打開所有這些源代碼,他或她應該自己開槍,”那麼你完全沒有這樣做。




這個的第二個重要用法(除了用一個局部變量來隱藏多個答案已經說過的),當從嵌套的非靜態類訪問外部實例時:

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



我問了一個類似的問題 ,但在可能的情況下,我嘗試複製已在.NET框架中的名稱,並在Java和Android框架中尋找想法。

看起來HelperManagerUtil是你不可避免的名詞,用於協調不包含狀態的類,通常是程序性的和靜態的。 另一個選擇是Coordinator

你可能會得到特別的紫色名稱,並去找MinderOverseerSupervisorAdministratorMaster ,但正如我所說的,我更喜歡將它保持為你所用的框架名稱。

在.NET框架中還可以找到其他一些常見後綴(如果這是正確的術語):

  • Builder
  • Writer
  • Reader
  • Handler
  • Container




java oop this