クラスで「これ」を使用する必要があるのはいつですか?


267

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

どうthis.method()ですか?使えますか?それを使用する必要があります。だけを使用method()した場合、デフォルトでは現在のオブジェクトに適用されませんか?

回答:


347

thisキーワードは、主に3つの状況で使用されています。最初で最も一般的なのは、変数参照を明確にするセッターメソッドです。2つ目は、現在のクラスのインスタンスを引数として別のオブジェクトのメソッドに渡す必要がある場合です。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代替コンストラクターを呼び出すために使用する。コメントで、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、インスタンス変数が参照されているという事実を明確にするために使用されることもありました(曖昧さをなくす必要性はありません)が、これは私の意見ではまれなケースです。


21
+1 これを引数として渡すこともできることを言及してください。これはスコープの明確化に使用されるだけではありません。
Alex Jasmin

12
もちろんthis(arg1, arg2, ...)、コンストラクタの中にもあります。
Thomas Eding

12
@Hazior:私は短い答えを書き、時間をかけてそれを追加する傾向があります。時にはそれは他の人の答えと重複することもあれば、そうでないこともあります。私の最新の編集の場合、trinithisはthis私が忘れていたもう1つの一般的な使用法を指摘したので、それを私の回答に追加しました。最終的にはSOの目的である全体としてより良い答えが得られるため、これで問題はないと思います。私はまた、トリニチスの場合と同様に、可能な限りクレジットを与えるようにしています。
William Brendel

4
ケース1と3の例があります。現在のクラスインスタンスが別のクラスのメソッドの引数として使用されているケース2の例を挙げていただけますか?
dbconfession 2014

4
@AStar私が長年取り組んできたほとんどのJavaコードベースでthisは、上記のセッターの例のように、明確化が本当に必要な場合にのみ使用されます。もちろん、コーディングスタイルと「ベストプラクティス」は、質問する相手によって大きく異なりますが、一般的には、合理的なパターンを選択して、それらに固執することをお勧めします。一貫性は、内部的には単一のコードベース内でも、読みやすさと保守性に大きく貢献します。
ウィリアムブレンデル2016

71

2つ目の重要な使用法this(多くの回答で既に述べられているように、ローカル変数で非表示にする以外に)は、ネストされた非静的クラスから外部インスタンスにアクセスする場合です。

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

this同じ名前のローカル変数が重複している場合にのみ使用する必要があり、ほとんどの人はそれを使用するだけです。(たとえば、setterメソッド)。

もちろん、使用するもう1つの理由thisは、IntellisenseがIDEでポップアップ表示されることです:)


1
しかし、それを調べた後、それをバックスペースする必要があります。プログラミングは疲れる!
LegendLength 2017年

25

唯一の必要性を使用するにはthis.、現在のスコープ内の別の変数は、同じ名前を共有し、あなたは(ウィリアムが説明のように)インスタンスメンバを参照したいとき修飾子があります。それとは別に、間の行動に違いありませんxとはthis.x


3
また、名前が重複している場合は、変数の名前を間違いなく不適切に指定しているため、名前を変更する必要があります。または、少なくとも、もっと良い名前を付けることができます。
CaffGeek

3
@チャド:Javaセッターメソッドでは一般的な方法です。ただし、セッターメソッドの外では、ステートメントは通常保持されます。
William Brendel

2
あなたが使用することをお勧めしますthis.xあなたのコードは、より明確に少し読ん作るために、コードの保守性/可読性はあなたが考慮しなければならないという要因もある...
ブライアンRehbein

1
@チャド:私は熱狂的に十分に同意することはできません。「これ」だからと言って良い主よ。2つの異なる変数に同じ名前を付けることができますが、なぜしたいですか?
BlairHippo

2
@ブレア:答えを読むと、セッターメソッドでこの方法を好まないことが明らかになりますが、多くの人がそうします(私はそのリストに自分自身を含めます)。値を受け取るセッターメソッドがある場合、渡される値は明らかに「新しい」値であるため、変数名に「新しい」を追加すると、パブリックAPIに不要な冗長性が追加されるようです。
Adam Robinson、

15

「this」は、あるコンストラクタを別のコンストラクタから呼び出すときにも役立ちます。

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

11

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

}

1
これは私が検索してここにたどり着いたときに私が欲しかった回答のタイプでしたが、コードの説明がないので、「this」について質問しているほとんどの人は、「return new user(this);」を理解できません。つまり、私はそうではありません...
nckbrz 14

Builderパターンは、構築時にパラメーターを明確に指定するために使用されます。どの文字列であるかを簡単に判別できない新しいUser(string、string)の代わりに、新しいBuilder()。setFirstName( "Jane")。setSurname( "Smith")。build()を使用します。これをBuilder.set ...()関数から返すので、連鎖させることができます。
ChrisPhoenix、2015

10

良い答えはたくさんありますが、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で読むのは非常に明確ですが、これは通常のテキストエディターで読むにはまったく悪夢になります。

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またはプロジェクトの設計中に、ルールに「これらすべてのソースコードをメモ帳で開いた場合、彼または彼女は頭の中で自分を撃たなければならない」というルールが含まれている場合は、これを行わなくても大丈夫です。


すばらしい回答@Jai
gaurav

撮影する最初の理由は、特にコードがすでにネストされている必要のない異なるクラスに
分割

@LuCio Lol true xD
Jai

7

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


1
this必要のないときに常にキーワードが表示される場合は、定型コードのため、コードが読みにくくなります。
AxeEffect 2013年

すべてのメンバーに「this」をプレフィックスとして付けることを要求するオープンソースプロジェクトに出くわしました。それとは別に、プロジェクトは非常によく書かれていますが、私は彼らとの宗教的な議論に入りたいと思っています。
LegendLength 2017年

4
@AxeEffect私はこれが本当に古いことを知っていますが... thisコードがlmaoを読みにくくすることはありません。
Xatenev 2017年

4

@William Brendelの回答は、3つの異なるユースケースを適切に提供しました。

ユースケース1:

これに関する公式のJavaドキュメントページは、同じユースケースを提供します。

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

2つの例を取り上げます。

これをフィールド使用し、これをコンストラクタで使用する

ユースケース2:

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

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

ユースケース3:

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

この投稿を参照

ビルダーを別のクラスに維持する(流れるようなインターフェイス)


2

グーグルはこれについて少し議論する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

メソッドでそれを使用することに関しては、あなたは効果について正しいです。それがあってもなくても同じ結果が得られます。使えますか?承知しました。あなたはそれを使うべきですか?あなた次第ですが、私が個人的にそれが明確さを追加しない無意味な冗長性であると考えると(コードが静的インポートステートメントでいっぱいに詰め込まれていない限り)、私はそれを自分で使用する傾向はありません。


4
これは規約ではなく、プログラム言語のスコープメカニズムです。あなたがリストしたもの--newX(私はパラメータxにpXを好む)を使用することは慣習です
Bill K

@ビルK:私はあなたがしている区別を理解していません。入力変数にx、またはnewX、pX、またはmangroveThroatWarblerXという名前を付けることを選択できます。「new」、「p」、または「Gruituitous Monty Python References」が規則になっているのに、規則ではなく設定している変数と同じ名前を付けることをどのように選択していますか?
BlairHippo

3
「Gratuitoud Monty Python References」は規約ではなく、法律です。
Adam Robinson

+1:このため、引数とメソッド変数にはクラス変数とは異なる命名基準を使用しています。引数/メソッド変数を省略し、クラス/インスタンス変数には完全な単語を使用します。
ローレンスドル

1
命名規則を使用してそれを解決することは、うーん、規則です。言語機能を使用してそれを解決する-その言語機能を決して使用しないか、常に使用することを選択するのは慣習だと思います...これを使用します。メンバーにアクセスするたびに規約になります。それは大した問題ではないと思う、私はこれも嫌いだ。
ビルK

2

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

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

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


1

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


1

this現在のオブジェクトへの参照です。同じ名前を持つローカル変数と現在のクラス変数を区別するためにコンストラクターで使用されます。例えば:

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

this別のコンストラクターから1つのコンストラクターを呼び出すためにも使用できます。例えば:

public class circle {
    int x;

    circle() { 
        this(1);
    }

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

0

一部のメソッドで「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

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

ウィリアムブレンデルの投稿やdbconfessionsに関するご質問、ケース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

Javaの「this」キーワードは、現在のクラスオブジェクトを参照するために使用されます。

Javaには「this」キーワードの6つの使用法があります。

  1. クラスレベルの変数へのアクセス:ローカルとクラスレベルの変数が同じ場合に主に使用されます
  2. クラスメソッドへのアクセス:これはデフォルトの動作であり、無視できます
  3. 同じクラスの他のコンストラクターを 呼び出すため
  4. 戻り値として「this」キーワードを使用:メソッドから現在のインスタンスを返すため
  5. メソッドの引数として 'this'キーワードを渡すPassing:現在のクラスインスタンスを引数として渡す
  6. コンストラクタの引数としてのこのキーワード:現在のクラスインスタンスを引数として渡すため

参照:https : //stacktraceguru.com/java/this-keyword-in-java


-8

現在のオブジェクトのメンバーが使用されていることを確認します。スレッドの安全性が懸念される場合、一部のアプリケーションは誤ったオブジェクトメンバー値を変更することがあります。そのため、これをメンバーに適用して、正しいオブジェクトメンバー値を使用する必要があります。

オブジェクトがスレッドセーフティに関係していない場合、どのオブジェクトメンバーの値を使用するかを指定する理由はありません。


これは本当にそうではありません。私はあなたがどのようなケースを考えているのかさえわかりませんが、例があなたが言っていることを理解するのに役立つかもしれません。
David Berger

1
はい。あなたが説明していることはスレッドセーフに関係していることを知っています。スレッドセーフを含むこの質問に対する正しい答えはありません。正しいオブジェクトを参照するために「this」が必要な場合、一度参照すると、同期されている場合に限り、メソッドまたは属性はスレッドセーフになります。参照があいまいな場合、マルチスレッド化が問題かどうかはあいまいになります。
David Berger、2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.