Javaは初めてですが、オブジェクトの割り当てについていくつか質問があります。たとえば、
Test t1 = new Test();
Test t2 = t1;
t1.i=1;
変数i
がTestクラス内で定義されていると仮定すると、t1とt2の両方が、変更t1.i=1
は両方に影響しますt1
およびt2
?実際に試してみたところ、正しかったようです。ただし、String
で同じことを試みると、変更は片側でのみ行われ、反対側は影響を受けません。この背後にある理由は何ですか?
編集:私が文字列で試したケース。
String s1 = "0";
String s2 = s1;
s1 = "1";
System.out.println(s1);
System.out.println(s2);
Stringは不変なので、ケースをテストすることで間違いを認識します。と思った状況s1="1"
文字列を変更すると、実際には「1」の参照がs1に返されます。それにもかかわらず、私の質問は残っています。しますTest t2 = t1;
t2とt1の両方が同じオブジェクトを指すようにするか、それぞれが独自のオブジェクトを持つようにしますか?この状況はJava上のすべてのオブジェクトに適用されますか?
あなたは正しいですが、文字列は特別なケースです。これらは不変であり、この場合プリミティブのように動作します。
@newacct
引用します http://docs.Oracle.com/javase/tutorial/Java/data/strings.html :
注:Stringクラスは不変なので、いったん作成されるとStringオブジェクトは変更できません。 Stringクラスには、文字列を変更するように見えるいくつかのメソッドがあります。文字列は不変なので、これらのメソッドが実際に行うことは、操作の結果を含む新しい文字列を作成して返すことです。
これが文字列を特殊なケースにする理由です。これがわからない場合は、引用で説明されているメソッドが新しい文字列を返さないことが予想され、予期しない結果が生じる可能性があります。
@ user1238193
あなたの次の質問を考えてみましょう:「テストt2 = t1; t2とt1の両方が同じオブジェクトを指すようにするか、それぞれが独自のオブジェクトを持つようになりますか?この状況はJava上のすべてのオブジェクトに適用されますか?」
t1とt2は同じオブジェクトを指します。これは、すべてのJavaオブジェクト(不変オブジェクトが含まれる))に当てはまります。
あなたはあなたの最初の仮定で正しいです。次のコード行で:
Test t1 = new Test();
新しいTestオブジェクトを作成すると同時に、それを参照するt1という名前のTest参照を作成します。
投稿したコードの2行目:
Test t2 = t1;
実際には別のテスト参照を作成し、それをt1が参照するのと同じオブジェクトを参照するように割り当てます。
そう t1.i = 1;
影響するだろう t2.i
それは結局同じオブジェクトだからです。
文字列に関しては、文字列は不変であり、インスタンス化された後は変更できません。
あなたの編集について:
String s1 = "0";
String s2 = s1;
s1 = "1";
System.out.println(s1);
System.out.println(s2);
実際に言うとき、彼らは異なる結果を印刷します
s1 = "1";
実際にはs1を別のStringオブジェクトにバインドしていますが、s2はまだ値「0」のオブジェクトを参照しています。
T1とt2の両方が同じオブジェクトを参照しているため、オブジェクトの状態のどの変化も両方に影響します。
文字列は不変オブジェクトです。したがって、まったく変更できません。 これを参照 Javaの不変オブジェクトの詳細については。
あなたは2つのケースで完全に異なることをしています。最初のケースでは、t1.i = 1;
を使用して、t1
が指すオブジェクトを変更しています。 2番目のケースでは、t1 = "1";
を使用して、別のオブジェクトを指すように参照を変更しています(t2 = t1;
を実行したときと同様)。
2番目のケースで行ったのと同じことをTest
に行うと、同じ結果が得られます(Test
に整数を取るコンストラクターがあると想定)。
Test t1 = new Test(5);
Test t2 = t1;
t2 = new Test(1); // Here we are assigning to the variable, just like your 2nd example
System.out.println(t1);
System.out.println(t2);
人々はString
は不変であると述べています。しかし、それは無関係であり、言語には「可変性」の概念がなく、「可変」クラスと「不変」クラスの動作に違いはありません。設定可能なフィールドや内部コンテンツを変更できるメソッドがない場合、クラスは「不変」と非公式に言います。 String
はそうです。しかし、変更可能なクラスは、それを変更するために何もしない場合とまったく同じように機能します。
[〜#〜]編集[〜#〜]
_Test t2 = t1;
_は、t2とt1の両方が同じオブジェクトを指すのか、またはそれぞれが独自のオブジェクトを持っているのですか?
はい。 _t2
_は新しい参照ですが、指示したため、同じオブジェクトを指します。タイプTest
の新しい参照_t2
_を作成し、_t1
_が指しているのと同じオブジェクトを指すようにします。
ただし、これをString
sで実行し、次に_s1 = "1" ;
_のようなことを実行すると、s1が別のStringオブジェクトを指すようになります。 s1 = new String(1);
という言葉で考えることができます。
文字列は他のオブジェクトと同様にオブジェクトです。したがって、それらに割り当てる変数は、テストオブジェクトの場合と同じように、オブジェクトのまったく同じインスタンスを参照します。
ただし、StringにはTestの場合のように設定できるフィールドがないため、基本的に同じテストを実行できないため、TestオブジェクトからStringオブジェクトにコードを移植する方法はないことに注意してください。
Long、intなどのプリミティブ型を使用すると、反対の動作が得られます。これらは「値によって」変数に割り当てられるため、
int t1 = 12;
int t2 = t1;
t1=15;
t2にはまだ値12があります