この記事を読む前に、ご自身の経験と理解に基づいて、まず Java 関数のパラメーターの受け渡し方法について考えて選択してください。
A. 値によって渡されますか?
B. 参照により渡されましたか?
C. 一部は価値観、一部は参照ですか?
正解はまだここでは発表されません。簡単な例を使用して、誰もが自分で答えを見つけられるようにしましょう:
1. まず、型 Value
public static class Value { private String value = "value"; public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
を定義します。2. newValue と、modifyValue を記述します。新しいオブジェクトの場合、modifyValue は入力パラメータの setValue メソッドを呼び出して、オブジェクトの値を変更します。
public static void newValue(Value value) { value = new Value(); value.setValue("new value"); System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); } public static void modifyValue(Value value) { value.setValue("new value"); System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); }
3. 簡単なテストコード
public static void main(String[] args) { Value value1 = new Value(); System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue()); // 将value1指向新的Value对象 newValue(value1); System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "\n"); Value value2 = new Value(); System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); // 使用object的set方法,修改对象的内部值 modifyValue(value2); System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); }4. 実行結果ログ:
Before modify, HashCode = 12677476, value = value In newValue, HashCode = 33263331, value = new value After modify, HashCode = 12677476, value = value Before modify, HashCode = 6413875, value = value In modifyValue, HashCode = 6413875, value = new value After modify, HashCode = 6413875, value = new value5. 上記のコードは、ペリフェラル A の値を取得します。またはオブジェクトを使用するには、このオブジェクトをパラメータとしてメソッドに渡し、メソッド内でオブジェクトのプロパティと動作を変更します。ただし、newValue とmodifyValue の 2 つのメソッドの変更メソッドは異なります。メソッドが呼び出された後のオブジェクトの外観は大きく異なります。この違いをどのように理解すればよいでしょうか?まず、値渡しと参照渡しの概念を確認しましょう:
* 値渡しとは、パラメーターが関数に渡されると、関数が元の値のコピーを受け取ることを意味します。したがって、関数がパラメーターを変更する場合、コピーのみが変更され、元の値は変更されません。
* 参照渡しとは、関数に引数を渡すと、関数は値のコピーではなく、元の値のメモリ アドレスを受け取ることを意味します。したがって、関数がパラメーターを変更すると、(関数ブロックの外側の呼び出しコード内の) パラメーターの元の値も変更されます。
正解: A——Java 関数はパラメータを値で渡します。
ログを分析します:
* 最初のログ出力では、value1 パラメーターが newValue メソッド内の新しいオブジェクトを指すように変更され、新しいオブジェクトの hashCode と値が出力されますが、newValue メソッドのドメインから飛び出した後です。 、メイン メソッドの value1 は変更されません。これは、値渡しの定義と特性と一致しています。参照渡しの場合、newValue(Value value) メソッドの呼び出し後に value1 が変更される必要があります。
* 2 番目のログ出力では、value2 は、modifyValue メソッド内で setValue 操作を実行しますが、hashCode は変更されませんが、modifyValue メソッドのドメインを離れた後、value2 は main メソッドで変更されます。 C++ を使用したことがある人は、この現象を次のように簡単に理解できます。関数のパラメータを参照で渡す!これは、C++ の参照渡しに非常に似ているためです。しかし、ここがまさに誤解に陥りやすいところです。
2 つのログの異なる現象の背後にある隠れた原理は、Java 言語はパラメータを値で渡し、オブジェクトは参照で渡します。Java で操作されるオブジェクトは実際には操作されているオブジェクトへの参照であり、オブジェクト自体は「ヒープ」に格納されます。 、オブジェクトの「参照」はレジスタまたは「スタック」に格納されます。
疑似コードは、newValue メソッドとmodifyValue メソッドの違いを説明しています。
newValue{ Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本 value_obj2 = new Value(); // value_obj2被创建、初始化在“堆“中 value_ref2 -> value_obj2; // value_ref2 指向value_obj2 value_ref2 ->value_obj2.setValue(“xxx”); // value_obj2 的value被修改 printValueObj2(); // 此处打印的是obj2的值 } modifyValue{ Value_ref2 = value_ref1; // 按值传入引用value_ref1,得到value_ref1的副本 value_ref2 ->value_obj1.setValue(“xxx”); // value_obj1 的value被修改 printValueObj1(); // 此处打印的是obj1的值 }
これで十分明らかです。 value1_ref1 がパラメーターとして関数に渡されると、関数ドメインで使用するために value1_ref2 のコピーが最初にコピーされます。この時点で、両方の ref は newObject 関数 [value = new Value();] で同じ value_obj コードを指します。 ] 実際、value1_ref1 は新しいオブジェクト value_obj2 を指します。この後の set 操作はすべて新しいオブジェクトに対する操作です。modifyValue 関数は set メソッドを通じて value_obj1 を直接操作します。これは newValue 関数とは異なります。
パラメータを値で渡す
メソッドを呼び出すときは、パラメータ リストで指定された順序でパラメータを指定する必要があります。たとえば、次のメソッドはメッセージを n 回連続で出力します。
public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) System.out.println(message); }
Example
次の例は、値渡しの効果を示しています。このプログラムは、2 つの変数を交換するために使用されるメソッドを作成します。
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; System.out.println("Before swap method, num1 is " + num1 + " and num2 is " + num2); // 调用swap方法 swap(num1, num2); System.out.println("After swap method, num1 is " + num1 + " and num2 is " + num2); } /** 交换两个变量的方法 */ public static void swap(int n1, int n2) { System.out.println("\tInside the swap method"); System.out.println("\t\tBefore swapping n1 is " + n1 + " n2 is " + n2); // 交换 n1 与 n2的值 int temp = n1; n1 = n2; n2 = temp; System.out.println("\t\tAfter swapping n1 is " + n1 + " n2 is " + n2); } }
上記の例のコンパイル結果と実行結果は次のとおりです。
Before swap method, num1 is 1 and num2 is 2 Inside the swap method Before swapping n1 is 1 n2 is 2 After swapping n1 is 2 n2 is 1 After swap method, num1 is 1 and num2 is 2
2 つのパラメーターを渡して、swap メソッドを呼び出します。興味深いことに、メソッドが呼び出された後、実際のパラメータの値は変化しません。
Java プログラミングにおけるメソッドのパラメータ受け渡しのより詳細な分析については、PHP 中国語 Web サイトに注目してください。