これは Java ではどこでも見られ、多くの用途があります。通常の状況では、このキーワードは非常に簡単に理解できますが、私が最初に学習したときによく理解できなかった質問を、この記事を通して皆さんのために記録しておきます。次へ
Java で this キーワードを通常使用するとき、これがこのクラスを呼び出しているメソッドの現在のインスタンスを表すことは誰もが知っています。通常であれば簡単に理解できるキーワードですが、学習を始めた当初はよく分からなかった疑問があったので、少しずつ理解できてきたので同じような悩みを持っている人がいるかもしれないので書いておきたいと思います。私としては質問ですが、他の人にも役立つかもしれません。まず、通常の状況におけるこれの役割を簡単に見てみましょう。たとえば、次のコード:
public class Leaf { private int i = 0; Leaf increment() { i++; return this; } void print() { System.out.println("i = " + i); } public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().print(); } }
Leaf クラスの main メソッドで、新しい Leaf インスタンス x を作成し、x インスタンスは increment()
メソッドを呼び出します。 increment() が通常のメソッドまたは void メソッドである場合、ここで検討する価値はありません。特別なのは、increment()
メソッドで返されるものが this であり、this this が作成したばかりの x を表すことです。 x は、increment() メソッド、つまり increment()
メソッドを呼び出しているため、これは明らかに Leaf の x インスタンスを表します。 increment()
方法。如果increment()是普通的方法或者void方法,这个地方就没有什么值得我们研究的了。特殊的是,在increment()
方法中,我们return的是一个this,这个this代表的就是我们刚刚创建的x。因为x正在调用increment()方法,所以,increment()
方法this就很明显代表的是Leaf的x实例了。
这看起来没有什么可讨论的,this就是代表的调用该方法的实例x。可是,假如我们把main()函数修改成下面的样子
public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().print(); Leaf y = new Leaf(); y.increment().increment().print(); }
以上修改的代码中,我们增加创建了一个Leaf实例y,然后y也连续调用调用了两次increment()。现在问题来了,假如 x,y同时调用的increment()方法,那么this到底能代表谁呢?你可能会觉得这有什么问题,x调用increment()方法,this就代表x, y调用increment()方法,this就代表y。可问题是,当我们讲调用方法的时候,在jvm层面上是找到Leaf类中increment()
方法所在的内存地址,然后在java虚拟机栈中创建栈帧.
然后在栈帧中执行方法里面的代码。现在看到了吧,也就是说,在jvm执行方法层面,没有所谓的x调用,y调用了,那么,方法中的this到底是怎么确定指向哪个实例的呢?
我们还是来看看Leaf类字节码中是怎么展示的,是不是我们漏了什么,如果我们没有把x实例或者y实例传递到方法里面去,那么,在jvm执行方法的时候,是不可能知道this具体指向哪个实例的。
到这里,我们看到在increment()
を次の 次に、スタック フレーム内のメソッドのコードを実行します。つまり、jvm 実行メソッド レベルでは、いわゆる x 呼び出しはなく、y が呼び出されます。では、メソッド内でこれがどのインスタンスを指すのかをどのように決定するのでしょうか。 Leaf クラスのバイトコードでどのように表示されるかを見てみましょう。x インスタンスまたは y インスタンスをメソッドに渡さないと、jvm がメソッドを実行します。これがどのインスタンスを指しているのかを知ることは不可能です。 この時点で、 上記の結論は私たち自身の推論ですが、これについて詳しく説明している本はありますか? 「java の考え方」では、このセクションは次のように説明されています: メソッド内にいて、現在のオブジェクトのハンドルを取得したいとします。このハンドルはコンパイラによって「秘密裏に」渡されるため、識別子は使用できません。ただし、この目的のための専用のキーワード、this があります。 その中で言及されているコンパイラーによって密かに渡されるハンドルが、ここでの隠しパラメータです。 以上がJavaキーワードの詳しい説明はこちら(パワーノード配置)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。public class B {
public B() {
System.out.println(this.getClass().getSimpleName());
System.out.println(((A) this).a);
}
}
public class A extends B {
public int a = 100;
public A() {
a = 200;
}
public static void main(String[] args) {
new A();
}
}
increment()
メソッドが配置されているメモリ アドレスを見つけて、Java でスタック フレームを作成することです。仮想マシンのスタック。increment()
メソッドにはエンコーディングにパラメーターがありませんが、パラメーターの数がバイトコードに 1 として表示されていることがわかります。慎重に結果を確認してください。それはすでに明白です。JVM がコンパイルを実行するとき、インスタンス メソッドでは、デフォルトでパラメーターが非表示で渡されます。このパラメーターは、現在呼び出されているインスタンスそのものです。たとえば、x を呼び出した場合は、非表示時に x が渡され、y を呼び出した場合は y が渡されます。したがって、this は、jvm 実行メソッド レベルで誰を指すかを決定できます。