値渡し/参照渡し
値の転送:メソッドが呼び出されると、それ实参
自体のコピーが割り当てられます形参
。メソッドでは、パラメーター値の変更は元の実際のパラメーターには影響しません。
参照による受け渡し:メソッドが呼び出されたとき、实参
への地址
転送形参
、今回のメソッドのパラメーター値の変更、操作は実際の引数です。
Javaで渡される値のみ
最初に、プログラミング言語のメソッド(または関数)へのパラメーターの受け渡しに関連するいくつかの専門用語を確認してください。
値による呼び出し:メソッドが呼び出し元から提供された値を受け取ることを示します。
参照による呼び出し:メソッドが呼び出し元から提供された変数アドレスを受け取ることを示します。
これは、(Javaだけでなく)さまざまなプログラミング言語でメソッドパラメーターを渡すメソッドを説明するために使用されます。
Javaプログラミング言語が常に採用されてい按值调用
ます。つまり、メソッドはすべてのパラメーター値のコピーを取得します。つまり、メソッドは渡されたパラメーター変数の内容を変更できません。
swap()シーン
int
型のa
合計b
の値を交換する関数を作成するように要求します
このswap()
方法では、a、bの値が交換され、A、Bには影響しません。aとbの値はAとBからコピーされただけだからです。つまり、aとbはAとBのコピーに相当し、コピーの内容がどのように変更されても、オリジナル自体には影響しません。
私たちが書く場合:
public class test{
public static void main(String[] args) {
int A = 2;
int B = 3;
swap(A, B);
System.out.println(A);
System.out.println(B);
}
public static void swap(int a, int b){
int tmp = a;
a = b;
b = tmp;
}
}
実行結果は次のとおりです。
2
3
AとBの値が交換されていないことがわかりました。なぜですか?
Javaで使用されているものをしているので值传递
、それが実行中に、と言うことですswap(int a, int b)
、パラメータのa
合計値、ここでは、b
ただのコピー合計は、A
およびB
関数の結果は、元の変更されませんA
合計B
値を。
養子縁組は
Integer
どうですか?
上記のint
タイプをに変更したInteger
場合swap(Integer a, Integer b)
、交換機能は実現しますか?
public class test{
public static void main(String[] args) {
Integer A = 2;
Integer B = 3;
swap(A, B);
System.out.println(A);
System.out.println(B);
}
public static void swap(Integer a, Integer b){
Integer tmp = a;
a = b;
b = tmp;
}
}
実行結果は次のとおりです。
2
3
まだ交換が完了していないことがわかります!
Integer
ソースコードを表示するには:
public final class Integer extends Number implements Comparable<Integer> {
}
変更されたストレージのInteger
使用を確認できます。変更された変数は再割り当てできないため、変数を渡すためにパラメーターを操作する場合、それは実際には操作です(Javaのパッケージタイプはデフォルトでこの方法で実装され、コピーは効率の向上とメモリ消費の削減に使用されます)。final
int
final
变量对象的副本
配列の場合はどうなりますか?
public static void main(String[] args) {
int[] arr = {
1, 2, 3, 4, 5 };
System.out.println(arr[0]);
change(arr);
System.out.println(arr[0]);
}
public static void change(int[] array) {
// 将数组的第一个元素变为0
array[0] = 0;
}
実行結果は次のとおりです。
1
0
ここでの方法は、オブジェクト自体のコピーではなくarray
、オブジェクトarr
コピーへの参照であり、同じ配列オブジェクトarray
をarr
指します。
それが一般的なオブジェクトである場合はどうなりますか?
多くのプログラミング言語(特にC ++とPascal)は、パラメーターを渡す2つの方法を提供します:値呼び出しと参照呼び出しです。
一部のプログラマー(この本の著者でさえ)は、Javaプログラミング言語对象
が参照呼び出しを使用していると考えています。実際、この理解は正しくありません。この誤解にはある程度の一般性があるため、この問題を詳しく説明するための反例を以下に示します。
class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
テスト:
public class test{
public static void main(String[] args) {
User A = new User("ali");
User B = new User("bd");
System.out.println("交换前name:" + A + "-->" + B);
swap(a,b);
System.out.println("交换后name:" + A + "-->" + B);
}
private static void swap(User a, User b) {
User tmp = a;
a = b;
b = tmp;
}
}
実行結果は次のとおりです。
交换前name:ali-->bd
交换后name:ali-->bd
まだ交換がないことがわかりました!
したがって、交換があるかどうかは、主にそれが変更されている变量(引用)
か変更されているかによって異なり堆里面的对象
ます。
交換前:
交換後:
上記の2つの図から、次のことがはっきりとわかります。このメソッドは、変数AとBに格納されているオブジェクト参照を変更しません。swap()メソッドのパラメーターaとbは、2つのオブジェクト参照のコピーとして初期化され、このメソッドはこれら2つのコピーを交換します。
では、2つの変数の値をどのように交換しますか?
- コンテナ(または配列)を使用する
例えば:
public class test{
public static void main(String[] args) {
int[] arr = {
2, 3};
int A = arr[0];
int B = arr[1];
swap(arr, 0, 1);
A = arr[0];
B = arr[1];
System.out.println(A);
System.out.println(B);
}
public static void swap(int[] arr, int a, int b){
int tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
}
実行結果は次のとおりです。
3
2
- 反射あり
public static void swap(Integer a, Integer b) throws Exception {
Field field = Integer.class.getDeclaredField("value");
field.setAccessible(true); //设置可以访问成员的私有不可变的变量
Integer tmp =new Integer(a.intValue());
field.set(a, b.intValue());
field.set(b, tmp);
}