2011-12-23 7 views
1

これは私の最初の質問StackOverflowです。これは、問題のコードです:この変数が影響を受けるのはなぜですか?

public class ListStuff { 
    public static void main(String [] args) { 

    String[] randomNames = {"Herbie", "Jaco", "Pat", "Michael"};   
    String[] reversedNames = revertNames(randomNames); 

    for (int i = 0; i < reversedNames.length; i++) { 
     System.out.println(reversedNames[i]); 
    } 
    } 

    public static String[] revertNames(String[] s) { 

    for (int i = 0; i < s.length/2; i++) { 
     String tmp = s[s.length - 1 - i]; 
     s[s.length - 1 - i] = s[i]; 
     s[i] = tmp; 
    } 

    return s; 
    } 
} 

このコードは、元に戻すとして罰金とreversedNames変数プリント実行されます。そこには苦情はありません。私の主な関心事は、String[] reversedNames = revertNames(randomNames);を実行すると、変数randomNamesも元に戻ります。私は決してrandomNames = blabla;randomNames変数を変更することはありません。なぜなら、私は引数として渡しているにもかかわらず、その変数が自分自身の復帰バージョンに変更され続ける理由がわかりません。

私は約1年間プログラミングしており、可変スコープなどの知識は非常に限られています。誰かが私を正しい方向に向けることができますか?

答えて

3

これは、値ではなく参照で配列を渡すためです。基本的に、これはreversedNames配列がまだrandomNames配列を指していることを意味します。したがって、一方を変更するともう一方が変更されます。当初

:ここ

は、変数の図である

randomNames <-------- s 

sアレイが依然としてrandomNames配列に戻っポイント:我々はrevertNames関数を入力として

randomNames 

!したがって、sを変更すると、randomNamesも変更されます。 randomNames

randomNames <--------- s <--------- reversedNames 

したがって、reversedNamesポイント:我々は機能を残したよう

機能を呼び出して終了した後:

randomNames <--------- reversedNames 

s配列は消えたが、reversedNamesはまだrandomNamesを指します。

revertNames関数の内部で一時変数を作成し、問題を修正するには:Javaで

public static String[] revertNames(String[] oldarray) { 
    // Create temporary array to avoid affecting original array 
    String[] s = oldarray.clone(); 
    ... 
+0

なぜdownvoteですか? – mc10

+0

うわー。 – user1114051

+0

私は今投票を変更しました...最初の回答では、この問題についての洞察はありませんでした。 +1 –

7

配列は参照型です。つまり、配列をrevertNamesメソッドに渡すと、そのメソッド内の変更もすべて外部に見えます。あなたは、このコードでrevertNames内の配列パラメータsを変更しているので:

String tmp = s[s.length - 1 - i]; 
s[s.length - 1 - i] = s[i]; 
s[i] = tmp; 

sの代わりに渡された元の配列randomNamesは、プロセスに変更されます。

1

revertNamesの本体の中に変数sがあります。これは配列であるオブジェクトへの参照です。実際の配列は配列randomNamesです。したがって、ソース配列の値は実際に変更されています。

配列を使用する場合。copy()は独立した配列を取得することができます。コピーは元の配列と同じ文字列を指しますが、文字列は安全であるため、安全です。

0

あなたは使用することができます。StringBufferのは:あなたが宣言した

String[] randomNames; 

を宣言した場合、Javaの

public class t { 
    public static void main(String [] args) { 

    String[] randomNames = {"Herbie", "Jaco", "Pat", "Michael"};   
    StringBuffer rev; 
    for (int i = 0; i < randomNames.length; i++) 
    { 
     rev=new StringBuffer(randomNames[i]); 
     System.out.println(rev.reverse().toString()); 
    } 
    } 
} 
0

配列は、すなわちを参照型です:)(

そのようないくつかのことを逆に文字列の配列であるオブジェクトへの参照を保持するローカル変数。

声明

String[] otherNames = randomNames; 

は、変数otherNamesに変数randomNamesの内容をコピーしますが、内容はあくまでも参考です。つまり、このステートメントは、otherNamesとrandomNamesの両方が同じ配列オブジェクトを参照するようにします。

メソッドパラメータとしてString[]を渡すと同じことが起こります。すなわち、ローカル変数srevertNamesであり、ローカル変数randomNamesmainである場合、同じ参照オブジェクト、つまり同じ配列オブジェクトを参照します。つまり、配列オブジェクトの状態は、srandomNamesの両方で表示されます。

厳密には、変数randomNamesは変更されていない(つまり、同じ配列を指している)ため、スコープとは関係ありません。修正されるのは、それが参照するオブジェクトです。

関連する問題