web-dev-qa-db-ja.com

クラスで "this"を使うべきなのはいつですか?

thisが現在のオブジェクトを参照していることを私は知っています。しかし、いつそれを使用する必要があるのか​​わかりません。たとえば、一部のメソッドでthis.xの代わりにxを使用した場合、違いはありますか? xは、対象となるメソッドにとってローカルな変数を参照する可能性がありますか私はこの方法でしか見られない変数を意味します。

this.method()はどうですか?使用できますか?私はそれを使うべきです。 method()を使用しただけでは、デフォルトでは現在のオブジェクトに適用されませんか。

234
Roman

thisキーワードは主に3つの状況で使用されます。最初で最も一般的なのは、変数参照を明確にするための設定メソッドです。もう1つは、現在のクラスインスタンスを別のオブジェクトのメソッドへの引数として渡す必要がある場合です。 3つ目は、コンストラクター内から代替コンストラクターを呼び出す方法としてです。

ケース1:変数参照を明確にするためにthisを使用する。 Javaのセッターメソッドでは、通常、設定しようとしているプラ​​イベートメンバー変数と同じ名前の引数を渡します。それから引数xthis.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を使用する。コメントでは、 trinithisthisの別の一般的な使い方を正しく示していました。 1つのクラスに複数のコンストラクタがある場合は、コンストラクタの最初の行で指定した別のコンストラクタを呼び出すために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がインスタンス変数が参照されているという事実を強調するために使用されているのを見たことがありますが、それは私の意見ではまれなケースです。

312
William Brendel

thisの2番目の重要な使用法(多くの答えが言っているようにローカル変数で隠すことに加えて)は、入れ子になった非静的クラスから外部インスタンスにアクセスするときです。

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

同じ名前のローカル変数が重複している場合は、thisを使用するだけでよく、ほとんどの人はそれを使用するだけです。 (設定メソッドなど)

もちろん、thisを使うもう一つの良い理由は、それがインテリセンスをIDEにポップアップさせるということです:)

44
froadie

this.修飾子を使用する唯一のneedは、現在のスコープ内の別の変数が同じ名前を共有していて、インスタンスメンバーを参照したい場合です(Williamが説明しているように)。それ以外は、xthis.xの動作に違いはありません。

23
Adam Robinson

"this"はあるコンストラクタを他のコンストラクタから呼び出すときにも便利です。

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

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

}
10
Kieren Dixon

変数名が重複していない限り、コードを読んでいるときは明確にするためです。

7
ChickenMilkBomb

良い答えはたくさんありますが、thisを至るところに置くもう1つの非常に小さな理由があります。通常のテキストエディタ(例:メモ帳など)からソースコードを開こうとした場合、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で読むのは非常に明らかですが、これは通常のテキストエディタで読むのは全くの悪夢になるでしょう。

エディタの "find"機能を使うまでは、fooがどこにあるのかを探すのに苦労します。それから同じ理由でgetStringFromSomewhere()を叫ぶでしょう。最後に、あなたがsが何であるかを忘れた後、その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. barWorldクラスに属しており、sはそのメソッドで宣言されているローカル変数であることがわかります。

もちろん、何かをデザインするときはいつでも、ルールを作ります。あなたのAPIやプロジェクトを設計している間、あなたのルールが「誰かがメモ帳でこれらのすべてのソースコードを開くならば、彼または彼女が頭の中で彼/彼女自身を撃つべきである」を含むなら、あなたはしてはいけませんこれ

6
Jai

@William Brendelの回答では、3つの異なるユースケースがありました。

ユースケース1:

this の公式Javaドキュメントページにも同じユースケースがあります。

インスタンスメソッドまたはコンストラクタ内では、これは現在のオブジェクト(そのメソッドまたはコンストラクタが呼び出されているオブジェクト)への参照です。これを使用して、インスタンスメソッドまたはコンストラクタ内から現在のオブジェクトの任意のメンバを参照できます。

2つの例があります。

Fieldでこれを使用するコンストラクタとこれを使用する

ユースケース2:

この記事では引用していないその他の使用例:thisを使用して、マルチスレッドアプリケーションの現在のオブジェクトを同期させ、データとメソッドの重要なセクションを保護することができます。

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

ユースケース3:

Builder patternの実装は、変更されたオブジェクトを返すためのthisの使用に依存します。

この記事を参照

ビルダーを別のクラスに保持する(流暢なインターフェース)

4
Ravindra babu

GoogleはSunのサイトで、これについて少し説明したページを作成しました。

あなたは変数について正しいです。メソッド変数とクラスフィールドを区別するためにthisを使うことができます。


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

しかし、私は本当にその慣習を嫌います。文字通り同一の名前を2つの異なる変数に与えることはバグのレシピです。私は以下の方針に沿って何かを好む。


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

同じ結果ですが、実際に代わりにxを参照しようとしているときに誤ってxを参照していたというバグの可能性はありません。

メソッドでそれを使うことに関しては、あなたは効果について正しいです。それがあってもなくても同じ結果が得られます。使えますか?もちろんです。あなたはそれを使うべきですか?あなたにもかかわらず、私が個人的には明瞭さを追加しないのは無意味な冗長性であると思うので(コードが静的import文でいっぱいに詰まっていない限り)、私はそれを自分で使うつもりはありません。

2
BlairHippo

以下は、Javaで「this」キーワードを使用する方法です。

  1. 現在のクラスインスタンス変数を参照するためのthisキーワードの使用
  2. this()を使用して現在のクラスコンストラクタを呼び出す
  3. 現在のクラスインスタンスを返すためのthisキーワードの使用
  4. メソッドパラメータとしてthisキーワードを使用

https://docs.Oracle.com/javase/tutorial/Java/javaOO/thiskey.html

2
roottraveller

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; 
    }
}
1
nouman shah

2つの変数が同じ名前の1つのインスタンス変数と他のローカル変数があるとき、我々はこれを使います。現在の実行中のオブジェクトを参照して、名前間の競合を回避します。

1
giri

いくつかの方法で "this.x"の代わりに "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()は呼び出しがこのオブジェクトによって行われていることを明確にします。

0
amit

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
  }
0
doc

William Brendel の投稿と dbconfessions 質問に関して、case 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");
    }
  }

}

これは、親子関係とオブジェクトとの関係を構築するときに使われるのを見たことがあります。ただし、簡潔にするために簡略化されています。

0
Alija