ホームページ >よくある問題 >Javaは値渡しですか、それとも参照渡しですか?

Javaは値渡しですか、それとも参照渡しですか?

WBOY
WBOYオリジナル
2022-09-08 14:47:0914335ブラウズ

Java は値の受け渡しです。値の受け渡しとは、メソッドを呼び出すときに実際のパラメーターのコピーがメソッドに渡されるため、メソッド内でパラメーターが変更されても実際のパラメーターには影響しません。 ; 渡すとき 基本型が渡されると、値のコピーが渡され、コピーされた変数への変更は元の変数に影響しません。参照型が渡されると、参照アドレスのコピーが渡されますが、コピーされた変数はアドレスと実アドレスは両方とも同じ実データを指すため、元の変数の値を変更できます。

Javaは値渡しですか、それとも参照渡しですか?

#このチュートリアルの動作環境: Windows 10 システム、DELL G3 コンピューター。

Java は値で渡されますか?

Java は値で渡されます。

基本型が渡される場合は、値のコピーが渡され、コピーされた変数への変更は元の変数には影響しません。参照型が渡される場合は、参照アドレスのコピーが渡されます。ただし、コピーされたアドレスと実アドレスは両方とも同じ実データを指しているため、String 型が渡されると、コピーされたアドレスも参照アドレスであり、参照アドレスを指しているにもかかわらず、元の変数の値を変更できます。同じデータ、文字列の値は変更できないため、元の変数の値は変更できません。

まず、参照渡しと値渡しについて説明しましょう。

  • 参照渡しとは、メソッド呼び出し時に実パラメータのアドレスをメソッドに直接渡すことで、メソッド内でパラメータを変更すると実パラメータに影響を与えます。

  • 値渡しとは、メソッドの呼び出し時に実際のパラメータのコピーをメソッドに渡すことを意味します。これにより、メソッド内でパラメータが変更されても、実際のパラメータには影響しません。 。

では、Java では、参照によって渡されるのでしょうか、それとも値によって渡されるのでしょうか?実際、この問題は継続的に議論されており、当局は明確な答えを出していません。しかし、私が理解している限り、Java は値の転送です。

まず簡単な例を見てみましょう。

public void test() {
    int a = 1;
    change(a);
    System.out.println("a的值:" + a);
}
private void change(int a) {
    a = a + 1;
}
// 输出
a的值:1

は、test() メソッドで基本型変数 a を定義し、次に、change() メソッドを呼び出して変数の変更を試みます。出力は元の値のままです。

まず最初に、メソッド内のローカル変数はスタックに格納されることを明確にする必要があります。基本型変数の場合、この変数の値は直接格納されます。参照型変数の場合、この変数の値は直接格納されます。アドレスはヒープ内の特定の値を指します。

上記の例では、change() メソッドの呼び出しによって渡される a は、実際には a 変数のコピーであり、実際の a ではありません。change() メソッドで変更されるのはコピーです。実際の a. には影響しません。

こうして見ると、確かに Java は値渡しをしていますが、次の例を見ると混乱するでしょう

public void test() {
   User user = new User();
   user.setAge(18);
   change(user);
   System.out.println("年龄:" + user.getAge());
}
private void change(User user) {
   user.setAge(19);
}
// 输出
年龄:19

ほら、オブジェクト内のプロパティが変更されています。このとき、渡される値が基本型の場合は値渡し、参照型の場合は値渡しであると誰かが結論付けました。参照。本当か?

この問題を分析するには、変数がどのように jvm に格納されるかを知る必要があります。

最初に基本型を見てみましょう。これは非常に単純です。変数は値をスタックに直接保存します。change() メソッドに渡されるのは変数のコピーなので、コピーされた変数を変更します。元の変数の値には影響しません。

次に、参照型を確認します。変数は、スタック内の参照アドレスを格納します。このアドレスは、以下に示すように、ヒープ内の特定の値を指します。

呼び出し時change()メソッドは変数を渡す際にその変数もコピーしますが、ここでのコピーはスタック内の参照アドレスのみでヒープ内のデータはコピーしませんので、 のようになります。次の図:

Javaは値渡しですか、それとも参照渡しですか?

変数はコピーされますが、変数が指すアドレスは同じであるため、変数内のデータが変更されると、元のデータに影響が残ります。ただし、スタック上の変数のアドレスを変更しても、元の変数には影響しません (たとえば、次のコード):

public void test() {
   User user = new User();
   user.setAge(18);
   change(user);
   System.out.println("年龄:" + user.getAge());
}
private void change(User user) {
   user = new User();
   user.setAge(19);
}
// 输出
年龄:18

これは、スタック内の変数のアドレスを変更するためのものです。スタックされますが、元の変数には影響しません。 Javaは値渡しですか、それとも参照渡しですか?

この時点では、誰もがほぼ理解していると思いますが、元の質問を振り返ると、String 型の変数が渡されています。String は参照型であり、元の変数が変更されるのは当然です。結果はどうですか? 変化はありませんか?

String 変数は特別です。String のソース コードから、String の値は内部の char[] 配列によって維持されていることがわかりますが、このデータは最終型として定義されています。したがって、String の値はは不変です。通常、String の値を変更するときは、実際には新しい String オブジェクトを作成します。たとえば、次のコードでは:

String a = "hello";
a = "world";

このコードでは、実際には、変数 a は world に変更されませんが、新しい文字列が作成されます。オブジェクト、このオブジェクトの値は world で、このオブジェクトの参照アドレスは a に割り当てられます。元の hello はまだヒープ内にありますが、この値は参照されず、gc 後にガベージ コレクションされます。しばらく。

String 変数によって渡された値のメモリ内の変更は次のとおりです:

Javaは値渡しですか、それとも参照渡しですか?

String は変数アドレスをコピーしますが、元の String の値を変更することはできません。String は不変であるため、change() メソッドで新しい String オブジェクトが作成されます。は新しいオブジェクトの値であり、元の変数は効果がありません。

さらに関連する知識については、FAQ 列をご覧ください。

以上がJavaは値渡しですか、それとも参照渡しですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。