web-dev-qa-db-ja.com

Javaオブジェクトの割り当て

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上のすべてのオブジェクトに適用されますか?

18
user1238193

あなたは正しいですが、文字列は特別なケースです。これらは不変であり、この場合プリミティブのように動作します。

@newacct

引用します http://docs.Oracle.com/javase/tutorial/Java/data/strings.html

注:Stringクラスは不変なので、いったん作成されるとStringオブジェクトは変更できません。 Stringクラスには、文字列を変更するように見えるいくつかのメソッドがあります。文字列は不変なので、これらのメソッドが実際に行うことは、操作の結果を含む新しい文字列を作成して返すことです。

これが文字列を特殊なケースにする理由です。これがわからない場合は、引用で説明されているメソッドが新しい文字列を返さないことが予想され、予期しない結果が生じる可能性があります。

@ user1238193

あなたの次の質問を考えてみましょう:「テストt2 = t1; t2とt1の両方が同じオブジェクトを指すようにするか、それぞれが独自のオブジェクトを持つようになりますか?この状況はJava上のすべてのオブジェクトに適用されますか?」

t1とt2は同じオブジェクトを指します。これは、すべてのJavaオブジェクト(不変オブジェクトが含まれる))に当てはまります。

14
Tom

あなたはあなたの最初の仮定で正しいです。次のコード行で:

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」のオブジェクトを参照しています。

5
NlightNFotis

T1とt2の両方が同じオブジェクトを参照しているため、オブジェクトの状態のどの変化も両方に影響します。

文字列は不変オブジェクトです。したがって、まったく変更できません。 これを参照 Javaの不変オブジェクトの詳細については。

3
Chandra Sekhar

あなたは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はそうです。しかし、変更可能なクラスは、それを変更するために何もしない場合とまったく同じように機能します。

2
newacct

文字列オブジェクトは不変


[〜#〜]編集[〜#〜]

_Test t2 = t1;_は、t2とt1の両方が同じオブジェクトを指すのか、またはそれぞれが独自のオブジェクトを持っているのですか?

はい。 _t2_は新しい参照ですが、指示したため、同じオブジェクトを指します。タイプTestの新しい参照_t2_を作成し、_t1_が指しているのと同じオブジェクトを指すようにします。

ただし、これをStringsで実行し、次に_s1 = "1" ;_のようなことを実行すると、s1が別のStringオブジェクトを指すようになります。 s1 = new String(1);という言葉で考えることができます。

2
Kazekage Gaara

文字列は他のオブジェクトと同様にオブジェクトです。したがって、それらに割り当てる変数は、テストオブジェクトの場合と同じように、オブジェクトのまったく同じインスタンスを参照します。

ただし、StringにはTestの場合のように設定できるフィールドがないため、基本的に同じテストを実行できないため、TestオブジェクトからStringオブジェクトにコードを移植する方法はないことに注意してください。

Long、intなどのプリミティブ型を使用すると、反対の動作が得られます。これらは「値によって」変数に割り当てられるため、

int t1 = 12;
int t2 = t1;
t1=15;

t2にはまだ値12があります

1
Andrea Parodi