タイトルの表現が間違っていると申し訳ありませんが、JavaFXで例を提供するのが最も簡単です。
primaryStage.setScene(new Scene(grid, 300, 275));
今私が理解していることから、このコードはSceneオブジェクトをインスタンス化して初期化していますが、宣言していません。これが事実である場合、それはメモリに格納されていないと言うのは正しいでしょうか?なぜこれをしたいのでしょうか?このSceneオブジェクトをsetSceneメソッドに正常に渡すことができても、Sceneオブジェクトを保存できないのはなぜですか。
これが事実である場合、それはメモリに格納されていないと言うのは正しいでしょうか?
あんまり。 Scene
オブジェクトがインスタンス化されています 定義により はメモリが割り当てられていることを意味します。
なぜこれをしたいのでしょうか?
ser232967 が指摘したように、ソースコードを整理するのに便利な方法です。 1行が同じように読みやすいのに、なぜ5行のコードを記述(そして他の人に強制的に読み込む)のでしょうか。
このSceneオブジェクトをsetSceneメソッドに正常に渡すことができても、Sceneオブジェクトを保存できないのはなぜですか。
weはもはやそのSceneオブジェクトを必要としないからです。 setScene
メソッドはそれを使用しました(そしておそらくそれへの参照を保存しました)が、それは私たちの問題ではないので、それについて心配する必要はありません。
これがそのシーンが使用される唯一の場所である場合、変数を宣言し、値を割り当てて、それを渡すことはあまり意味がありません。
同様に、次のことを行うことができます。
int x = 300;
int y = 275;
primaryStage.setScene(new Scene(grid, x, y));
例のように、1つのステートメントで合理的にカプセル化できる場合は、それを行う方が理にかなっています。上記のように使い捨て変数を宣言すると、コードが乱雑になる可能性があります。
これが事実である場合、それはメモリに格納されていないと言うのは正しいでしょうか?
いいえ。オブジェクトはまだメモリに確実に保存されています。宣言がない場合でも、別のオブジェクト内からの参照を参照できます。これは、オブジェクトprimaryStage
のセッターメソッド内でオブジェクトを初期化したためです。
それをまったく参照せずにインスタンス化して、次のように書いた場合:
new Scene(grid, 300, 275);
それはまだメモリに保存されますが、到達不可能であり、参照(参照)がないため、最終的にはガベージコレクションされる可能性が高くなります。
オブジェクトをインスタンス化すると、宣言があるかどうかに関係なく、heapメモリ空間に保存されます。ヒープメモリは、オブジェクトを格納するために割り当てられるメモリ領域です。 Stackメモリは、ローカル変数を格納するために割り当てられたメモリ内の領域です。
あなたの例では、Scene
セッターメソッド内でprimaryStage
を初期化しました。つまり、primaryStage
がScene
を指す参照を持っているため、クリーンアップできません。ガベージコレクターによって。したがって、Scene
は、少なくともprimaryStage
が存在する限りメモリに残ります。
オブジェクトにはライフサイクルがあります。つまり、JVMがオブジェクトに到達できる限り、オブジェクトはメモリ内に存在します。オブジェクトの存続期間を継続するには、それを指す参照変数が必要です。そのオブジェクトを指す参照変数がない場合、そのオブジェクトはガベージコレクションの対象になります。これは、JVMがこのオブジェクトを決定したプロセスです。新しいオブジェクトを格納するためのスペースを空けるために、メモリはもはや有用ではなく、そのオブジェクトを削除する可能性があります。
メモリ管理の詳細については、この件に関するOracleのドキュメントを確認してください。スタックとヒープの違いを理解できます。メモリだけでなく、JVMに組み込まれたガベージコレクションのさまざまなタイプのいくつか。 https://docs.Oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/garbage_collect.html
なぜこれをしたいのでしょうか?
一般的なケースは、まだ持っていないオブジェクト参照を必要とするメソッドを呼び出すことです。非静的メソッドを呼び出したいが、それを呼び出すための既存のインスタンスがない場合があります。以下に例を示します。
_class Orange {
void printOrange(){
System.out.print("Oranges are my favorite fruit.");
}
}
class OrangeJuice extends Orange {
public static void main(String[] args) {
// some other useful code for OrangeJuice
new Orange().printOrange();
}
}
_
この例では、出力は次のようになります。
_Oranges are my favorite fruit.
_
単にprintメソッドを呼び出すために参照変数を作成する必要はなかったので、これがOrangeクラスを使用する唯一の方法であるなら、なぜ時間とメモリを無駄にするのでしょうか。この場合、次の間にprintOrange()
を呼び出すことができます。
printOrange()
を呼び出すだけで初期化したOrange
オブジェクトの存続期間を短縮することにより、ヒープ領域を効率的に使用する宣言なしでインスタンス化するもう1つの理由は、大量のデータを処理するプログラムの場合が一般的ですが、スタックオーバーフローを防ぐためです。スタックスペースでローカル変数が上限に達したために、スタックスペースがストレージスペースの過剰使用によりクラッシュした場合です。
オブジェクトは実行時にのみ宣言/作成できます。コンパイルして例外エラーなしで実行できるからといって、最終的にクラッシュできないわけではありません。オブジェクトを大規模に宣言し、ガベージコレクションを許可しない場合、メモリの過剰使用によりプログラムがクラッシュする可能性があります。
参照変数はスタックメモリに格納されるため、宣言をできるだけ少なく(プログラムの機能に影響を与えずに)することで、これが発生する可能性を減らします。もちろん、これは通常、大規模なプログラムや、大量のデータストリームを処理するプログラムに関連する問題です。
この
Scene
オブジェクトをsetScene
メソッドに正常に渡すことができても、Scene
オブジェクトを保存できないのはなぜですか?
コンパイラは、メモリ管理の必要性を理解するように設計されています。オブジェクトを利用するために明示的な宣言を行う必要はありません。宣言はメモリとビルド時間を要します。
この場合、Youdidオブジェクトを「保存」します。オブジェクトScene
のセッターメソッドsetScene
内でprimaryStage
を初期化することにより、メモリ内のそのScene
のスペースへのポインターを作成しました。現在はそこにあり、primaryStage
オブジェクトを通じて参照できます。
オブジェクト指向の結果を控えた出力を生成するための非静的メソッドを呼び出す場合、コンパイラーはその結果を生成するための足がかりとしてオブジェクトを必要とします。これにより、コードをより効率的に使用できるようにするために、メソッドを呼び出すために参照変数が通常使用される場所の代わりにインスタンス化を配置できます。
宣言なしでオブジェクトをインスタンス化することにより、特定のケースでは、基本的に「setScene
メソッドを呼び出したいのですが、Scene
オブジェクトを構築するには、そのためにScene
オブジェクトを厳密にインスタンス化し、コードをより単純にします。」