1. 参照変数
Java 言語には、プリミティブ変数とその他すべての 2 種類の変数があります。たまたまですが、これからは「その他すべて」について話します。
実際には、プリミティブ変数と参照変数があると言った方が正確です。では、これらの参照変数とは何でしょうか?
変数が値を直接格納するプリミティブ型とは異なり、参照変数はオブジェクトへの参照を格納します。つまり、メモリ内のどこかにオブジェクトが存在し、参照変数はメモリ内のこのオブジェクトのアドレス (オブジェクトへの参照) を格納するだけです。
プリミティブ型のみが値を変数内に直接保存します。他のすべての型はオブジェクト参照のみを保存します。ところで、変数String
と配列変数という 2 種類の変数についてはすでに説明しました。
配列と文字列はどちらもメモリ内のどこかに保存されているオブジェクトです。String
変数と配列変数には、オブジェクトへの参照のみが格納されます。
int a, int b and double d
値を内部に格納するプリミティブ変数です。
変数String str
は参照であり、メモリ内のオブジェクトへのアドレス (参照) を格納しますString
。
プリミティブ型の変数にプリミティブ値を代入すると、その値がコピー (複製) されます。参照変数を割り当てる場合、オブジェクトのアドレスのみがコピーされ、オブジェクト自体は コピーされません。
2. 参考文献とは何ですか?
参照変数とプリミティブ変数の根本的な違いは何ですか?
プリミティブ変数はボックスのようなもので、その中に値を格納できます。参照変数は、電話番号が書かれた紙に似ています。
車と車の鍵
友人の誕生日に車をプレゼントすることにしたと想像してください。箱に入れて持ち運ぶことはできません。そのためには車が大きすぎます。
車のキーだけを入れるのに十分な大きさの箱に入れて提示すると、はるかに便利です。あなたの友人は、箱から鍵を取り出すときにすべてを理解するでしょう。キーを渡すだけで済むため、車全体を持ち運ぶ必要はありません。
個人とその電話番号
あるいは、ここで別の比較をしてみましょう。人とその電話番号です。電話番号はその人そのものではありませんが、電話番号は彼女に電話をかけたり、情報を尋ねたり、指示を与えるために使用できます。
同様に、参照はオブジェクトと対話するために使用されます。すべてのオブジェクトは参照を使用して相互に対話します。「人を交換する」のではなく、単に電話番号を交換するだけです。
プリミティブ変数に値を代入すると、その値がコピー (複製) されます。参照変数に値を割り当てる場合、オブジェクトのアドレス (電話番号) のみがコピーされ、オブジェクト自体はコピーされません。
参照にはもう 1 つの利点があります。オブジェクト参照をメソッドに渡すと、メソッドはその参照を使用してオブジェクトを変更 (変更) し、そのメソッドを呼び出し、オブジェクト内のデータにアクセスできるようになります。
3. 参照の割り当て
参照変数を割り当てる場合、メモリ内のオブジェクトのアドレスのみが割り当てられます。オブジェクト自体は現れたり消えたりしません。
このアプローチにより、大量のメモリのコピーが回避されます。非常に大きなオブジェクトをメソッドに渡す必要がある場合は、オブジェクト参照を渡すだけで済みます。参照が占めるスペースは大幅に少なくなります。
すべての参照変数のサイズは (型に関係なく) 同じで、4 バイト (int と同様) です。しかし!アプリケーションが 64 ビット Java マシンで実行されている場合、すべての参照のサイズは 8 バイト (64 ビット) になります。
さらに、参照は相互にのみ割り当てることができます。参照を変更したり、参照変数に任意の値を割り当てたりすることはできません。
コード | 説明 |
---|---|
|
これは許可されています |
|
でもこれは許されない |
|
そしてこれは許されない |
4.null
参考資料
まだ何も割り当てられていない場合、参照変数には何が格納されるのでしょうか?
null参照を格納します。null
は、参照がないこと (空の参照) を意味する特別な Java キーワードです。値null
は任意の参照変数に割り当てることができます。
null
何らかの参照が割り当てられていない限り、すべての参照変数はそうです。
例:
コード | 説明 |
---|---|
|
変数 String name のデフォルト値は ですnull 。変数 int age のデフォルト値は です0 。 |
値が割り当てられていないローカル変数は、プリミティブ型と参照型の両方で初期化されていないとみなされます。
変数に何らかのオブジェクトへの参照が格納されており、その変数の値をクリアしたい場合は、その変数に null 参照を割り当てるだけです。
コード | 説明 |
---|---|
|
s 店舗null 。文字列オブジェクトs への参照をストアします。s null |
5. メソッドへの参照の受け渡し
メソッドに参照型のパラメータがある場合、非参照変数を操作する場合と同じ方法で値がメソッドに渡されます。パラメーターには、他の変数の値が割り当てられるだけです。
例:
コード | 説明 |
---|---|
|
fill 渡された配列 ( array ) を渡された値 ( ) で埋めますvalue 。 |
fill
メソッドが呼び出されると、array
パラメーターには配列への参照が割り当てられますdata
。変数value
には文字列オブジェクト (「Hello」) への参照が割り当てられます。
メソッドを呼び出す前の メモリは次のようになりますfill
。
メソッドの実行中の メモリは次のようになりますfill
。
および変数は、メモリ内の同じコンテナを参照します (参照を格納します) data
。array
変数value
には、文字列オブジェクト ( ) への参照が格納されます"Hello"
。
配列のセルには、"Hello"
オブジェクトへの参照が格納されるだけです。
実際、オブジェクトは複製されず、参照のみがコピーされます。
6. C/C++言語との比較
インタビューで、Java プログラマーは、データが Java のメソッドにどのように渡されるのかを尋ねられることがあります。また、データが参照によって渡されるのか、値によって渡されるのかが疑問になることがあります。
この質問は C++ からのものですが、Java ではあまり意味がありません。Java では、パラメータには常に引数の値が単純に割り当てられます。したがって、正しい答えは「値による」になります。
ただし、「プリミティブ型は値によって渡され、参照型は参照によって渡される」という反論がすぐに聞こえるかもしれないので、自分の立場を説明する準備をしてください。
この問題の原因は、以前は Java プログラマの多くが C++ プログラマであったという事実にあります。そのプログラミング言語では、パラメータをどのようにメソッドに渡すかという問題が非常に重要でした。
Java では、すべてが明確です。プリミティブ型は値を格納し、参照型も値 (参照) を格納します。それは変数が値とみなされるかどうかの問題です。
C++ では、変数にはオブジェクトへの参照とオブジェクト自体の両方を格納できます。プリミティブ型についても同様で、プリミティブ変数は値を格納したり、変数を への参照として宣言したりできますint
。したがって、混乱を避けるために、C++ プログラマーは常に、参照へのオブジェクトを参照と呼び、オブジェクト自体を値と呼びます。
C++ では、1 つの変数にオブジェクトが含まれているが、もう 1 つの変数にはそのオブジェクトへの参照が含まれているという状況が簡単に発生します。したがって、変数が何を保存するか、つまりオブジェクト自体、またはそのオブジェクトへの参照だけが非常に重要でした。オブジェクトがメソッドに渡されると、オブジェクトはコピーされます (値によって渡される場合) が、コピーされません (参照によって渡される場合)。
Java では、この二重性は存在しないため、正しい答えは、引数は value によって Java メソッドに渡されるということです。参照変数について話している場合、この値は参照であるというだけです。
GO TO FULL VERSION