この記事では、java に関する関連知識を提供します。主に、Java の文字列と配列のパラメーターの受け渡しに関連する問題を紹介します。Java が値渡しのみである理由を見てみましょう。皆さんのお役に立てれば幸いです。
推奨学習: 「java 学習チュートリアル 」
最初に明確にしておきたいのは、Java では値の受け渡しのみが行われるということです。 !値のみが渡されます。理論的根拠は「Javaで考える」から来ています。次のステップでは、Java が値渡しのみである理由を詳しく説明します。
Java には基本型と参照型の 2 つのデータ型と、特殊な型 String があるため、主に 3 つの側面から説明できます。
最初にコードを見てください
public class Demo01 { public void change(int a) { System.out.println("副本a 的初始值" + a); a = 20; System.out.println("副本a 的新值值" + a); } public static void main(String[] args) { int a = 10; Demo01 d = new Demo01(); d.change(a); System.out.println("change方法执行后的值" + a); } }
分析:
Java では、基本データ型は値の転送に続くため、オブジェクト d Change() メソッドでは、元のデータ a のコピーがメソッドのパラメーターに渡されるだけです。最初は元のデータ a とコピー a の値は両方とも 10 です。a=20 が呼び出された後は、実行すると、コピー a の値は 20 になります。
実行結果は次のようになります:
原理については、以下の図を参照してください
最初にコードを見てください
public class Demo02 { char[] ch = {'a', 'b', 'c'}; public void change(char ch[]) { System.out.println("方法中ch[0]的初始值:" + ch[0]); ch[0] = 'g'; System.out.println("方法中ch[0]执行后的新值:" + ch[0]); } public static void main(String[] args) { Demo02 d = new Demo02(); System.out.println("对象d中数组的初始值是:"+d.ch); d.change(d.ch); System.out.println("对象d中数组的最终值是:"+d.ch); } }
分析:
参照型がパラメータとして渡される場合、それは値の転送でもあります。このとき、アドレス値のコピーが渡されますが、これら 2 つのアドレスは同じ場所を指します。コピーアドレスが変更されていない場合、コピーアドレスが指すデータに対する操作は元のデータの値に影響を与えます。メソッド内の ch[] 配列と元の ch[] 配列は同じデータを指すため、初期段階では ch[0] は 'a' を指し、その後、コピー内の ch[0] に新しい値が割り当てられます。 「g」になります。
したがって、実行結果は次のようになります。
原理については、以下の図を参照してください。
最初にコードを見てください
public class Demo03 { public void change(String str2) { System.out.println("方法中str2初始值" + str2); System.out.println("方法中str2初始hashcode值" + str2.hashCode()); str2 = "bbb"; System.out.println("方法中str2赋值后:" + str2); System.out.println("方法中str2赋值后hashcode值:" + str2.hashCode()); } public static void main(String[] args) { String str1 = new String("aaa"); System.out.println("原始字符串str1的hashcode值:" + str1.hashCode()); Demo03 d = new Demo03(); d.change(str1); System.out.println("方法调用后str1的值" + str1); } }
分析:
文字列は特別なデータ型であり、その最下層は最後の char[] 配列であり、これはできません変更される可能性があるため、パラメータとして文字列を渡すと、特殊な配列として操作できます 同様に、コピーには元のオブジェクト参照のコピーが与えられます このとき、コピーオブジェクトの参照はと元のオブジェクトの参照は両方とも元の文字列を指します。位置、つまり str2 が最初に初期化されるとき、それが指すアドレスは、元のオブジェクト str1 が指す位置、つまり初期ハッシュコード値と一致します。 str2 のハッシュコード値は、元のオブジェクト str1 のハッシュコード値と同じです。str2 が str2="bbb" によって操作された後、 文字列の不変性により、str2 はこの時点で新しいオブジェクト参照を指します。 , このときstr2は「bbb」の位置を指すことになります。 str2 のハッシュコード値は変更されますが、str1 の元のオブジェクト参照は変更されておらず、「aaa」も変更されていないため、str1 は引き続き「aaa」を指します。 実行結果は次のとおりです:
より具体的な文字列の例を見てみましょう:
public class Demo04 { public static void main(String[] args) { StringBuffer s = new StringBuffer("hello"); StringBuffer s2 = new StringBuffer("hi"); test(s, s2); System.out.println("方法調用后s的值:" + s); System.out.println("方法調用后s2的值:" + s2); } static void test(StringBuffer s3, StringBuffer s4) { System.out.println("方法初始化時s3的值" + s3); System.out.println("方法初始化時s4的值" + s4); s4 = s3; s3 = new StringBuffer("new"); System.out.println("第一步变化后s3的值" + s3); System.out.println("第一步变化后s4的值" + s4); s3.append("boy"); s4.append("gril"); System.out.println("第二步变化后s3的值" + s3); System.out.println("第二步变化后s4的值" + s4); } }
今回はまず結果を見てみましょう:
次に分析します:
メソッドが実行される前に、文字列 s1 と s2 が指す場所はそれぞれ「hello」と「hi」です。これは疑いの余地がありません。 ,
(1) 次にメソッドに入ります. メソッド内のパラメータ s3 と s4 は上記の例と同様に初期化されます. このとき、それらは s1s2 と同じ位置を指すか、s1s2 がコピーを与えますこのとき、s3s4の値 "hello"と"hi"の場合
(2) 次に、s4=s3を実行します。この操作は、s3のオブジェクトをs4に参照する操作です。このとき、s4 は "hello"; s3=new StringBuffer("new "); この操作は、s3 に新しいオブジェクト参照を与えるのと同じであることに注意してください。s3 は文字列が "new" である場所を指しているため、今回は s3 = "new", s4 = "hello"
(3) 次に s3.append("boy");s4.append("gril"); StringBuffer の append メソッドが次のことを行うことに注意してください。 s3s4 の新しいオブジェクト参照を指しているわけではありません。操作はオリジナルに基づいて実行されるため、操作が完了すると、s3 = "newboy"、s4 = "hellogril"
(4) この時点でメソッドが呼び出されますが、戻ってプロセス中の s3s4 が s1s2 に与える影響を確認してみましょう。
——- A. まず、s3 は s1 と同様に "hello" を指し始め、次に s3 の新しいオブジェクト参照 "new" を作成します。この時点で、s3 と s1 には 0.5 セントの関係はありません。 s3 は append (boy) を実行し、s3 = "newboy";
——– B. s4 と s2 はどちらも最初に "hi" を指し、その後 s3 はその初期値 (つまり、s1 のコピー) を与えます。 ) から s4。この時点で、s4 は「hello」を指します (これにより、s4 と s1 の間に関係が作成されます)。s4 と s1 は同じ場所を指しているため、s4 は追加 (グリル) 操作を実行します。ポイントが変更され、s4=s1="hellogrill" となります。
——- C. 次に、s2 が指すオブジェクト「hi」は変更されておらず、s1 が指す「hello」は、追加 (「グリル」) 操作により「hellogril」になっていることがわかります。
基本データ型をメソッドの仮パラメータとして使用する場合、メソッド本体の仮パラメータを変更しても、メソッドの値には影響しません。
参照データ型をメソッドの仮パラメータとして使用する場合、仮パラメータが指すデータの内容がメソッド本体内で変更されると、影響を受けます。仮パラメータ変数と実パラメータ変数は同じヒープ領域を共有するため、実パラメータ変数の値;
メソッドの仮パラメータとして参照データ型を使用する場合、ポインタが仮パラメータ変数の値がメソッド本体で変更されても、実際のパラメータ変数の値には影響しないため、仮パラメータ変数と実パラメータ変数はそれぞれ異なるヒープ領域を指します。最後の例が最もわかりやすい説明です。 。
文字列パラメータに関しては、文字列の基礎となる層が最終型 char[] であるため、そのパラメータ変数のポインティングが変更されたかどうかにも依存します。 String s = " aaa を使用する場合" または String s = new String("aaa") の場合、 s に対して新しいオブジェクト参照が作成されます。ただし、append() メソッドが呼び出されると、新しいオブジェクトを指すのではなく、元の指すオブジェクトが変更され、そのオブジェクトと共有されているオブジェクト参照も変更されます。
最後に繰り返しますが、Java には参照転送はなく、値転送のみです。参照型は特殊な値転送です (そのアドレスのコピーがパラメータに与えられます)。ただし、基本的なデータ型とは異なります。アドレスが指すオブジェクトが変更されると、共有の理由により元のオブジェクトも変更されます)。
推奨学習: 「Java チュートリアル 」
以上がJAVA での文字列と配列のパラメータ受け渡しについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。