Javaキーワードの詳しい説明はこちら(パワーノード配置)

黄舟
リリース: 2017-03-31 10:28:27
オリジナル
1442 人が閲覧しました

これは 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()

議論することはないようです。これはメソッドを呼び出すインスタンス x です。ただし、上記の変更されたコードで main()関数

を次の

に変更すると、追加の Leaf インスタンス y を作成し、その後 y も increment() を 2 回連続して呼び出しました。ここで問題は、x と y が同時に increment() メソッドを呼び出した場合、これは誰を表すのかということです。これには何か問題があると思われるかもしれませんが、x が increment() メソッドを呼び出すと、これは x を表し、y が increment() メソッドを呼び出すと、これは y を表します。しかし問題は、メソッドの呼び出しについて話すとき、JVM レベルで Leaf クラスの increment() メソッドが配置されているメモリ アドレスを見つけて、Java でスタック フレームを作成することです。仮想マシンのスタック。

次に、スタック フレーム内のメソッドのコードを実行します。つまり、jvm 実行メソッド レベルでは、いわゆる x 呼び出しはなく、y が呼び出されます。では、メソッド内でこれがどのインスタンスを指すのかをどのように決定するのでしょうか。 Leaf クラスのバイトコードでどのように表示されるかを見てみましょう。x インスタンスまたは y インスタンスをメソッドに渡さないと、jvm がメソッドを実行します。これがどのインスタンスを指しているのかを知ることは不可能です。

この時点で、increment() メソッドにはエンコーディングにパラメーターがありませんが、パラメーターの数がバイトコードに 1 として表示されていることがわかります。慎重に結果を確認してください。それはすでに明白です。JVM がコンパイルを実行するとき、インスタンス メソッドでは、デフォルトでパラメーターが非表示で渡されます。このパラメーターは、現在呼び出されているインスタンスそのものです。たとえば、x を呼び出した場合は、非表示時に x が渡され、y を呼び出した場合は y が渡されます。したがって、this は、jvm 実行メソッド レベルで誰を指すかを決定できます。

上記の結論は私たち自身の推論ですが、これについて詳しく説明している本はありますか? 「java

プログラミング

の考え方」では、このセクションは次のように説明されています: メソッド内にいて、現在のオブジェクトのハンドルを取得したいとします。このハンドルはコンパイラによって「秘密裏に」渡されるため、識別子は使用できません。ただし、この目的のための専用のキーワード、this があります。

その中で言及されているコンパイラーによって密かに渡されるハンドルが、ここでの隠しパラメータです。

🎜 ここまでの説明は非常に明確である必要があり、JVM レベルで理解できました。それでは、以下の例を見て、基底クラス B のこれが何を表すか考えてみませんか? 🎜rrreee🎜この例は元々、Java に 🎜継承🎜 構造がある場合にクラスがどのように初期化されるかを理解することを目的としていましたが、クラス B の 🎜コンストラクター🎜 は非常に特殊です。これはクラス B のコンストラクターで出力されます。SimpleName は A です。通常、この状況に遭遇した場合、クラス B で this によって出力される SimpleName は B であるはずですが、ここでは A ですか?なぜ? 🎜🎜これについては、上記の説明の過程ですでに触れましたが、スタック フレームを作成するために Java メソッドを呼び出すとき、JVM は現在のインスタンスを密かに渡します。したがって、A のコンストラクターを実行すると、親クラス B のコンストラクターがデフォルトで呼び出されます。親クラス B のコンストラクターを呼び出すと、B が呼び出されるため、密かに渡される現在のインスタンスは A のインスタンスになります。 A のコンストラクターなので、ここでは代わりに A を表します。 🎜

以上がJavaキーワードの詳しい説明はこちら(パワーノード配置)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート