23

私はJavaを初めて使用しますが、オブジェクトの割り当てに関していくつか質問があります。例えば、

Test t1 = new Test();
Test t2 = t1;
t1.i=1;

変数がTestクラス内で定義されていると仮定すると、t1とt2の両方が、変更がとの両方に影響を与えるi同じオブジェクトを指していると仮定するのは正しいですか?実際にテストしてみたところ、正しかったようです。ただし、同じことを試してみると、変更は一方の側でのみ発生し、もう一方の側は影響を受けません。この背後にある理由は何ですか?t1.i=1t1t2String

編集:私がStringで試したケース。

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

Stringは不変であるため、Stringでケースをテストすることで自分の間違いに気づきます。文字列を変更すると思っs1="1"たのは、実際には「1」の参照をs1に返すことです。それにもかかわらず、私の質問は残っています。t2とt1の両方が同じオブジェクトを指しているのでしょうかTest t2 = t1;、それともそれぞれが独自のオブジェクトを持っているのでしょうか。この状況は、Java上のすべてのオブジェクトに当てはまりますか?

4

8 に答える 8

19

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

@newacct

http://docs.oracle.com/javase/tutorial/java/data/strings.htmlを引用します:

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

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

@ user1238193

次の質問を検討してください。「テストt2=t1。t2とt1の両方が同じオブジェクトを指すようにしますか、それともそれぞれに独自のオブジェクトがありますか?この状況はJavaのすべてのオブジェクトに当てはまりますか?」

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

于 2012-06-13T09:17:47.287 に答える
8

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

Test t1 = new Test();

新しいテストオブジェクトを作成すると同時に、それを参照するためにt1という名前のテスト参照を作成します。

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

于 2012-06-13T09:22:01.177 に答える
5

あなたは2つのケースで完全に異なることをしています。最初のケースでは、を使用してt1.i = 1;、が指すオブジェクトを変更していますt1。2番目のケースでは、を使用してt1 = "1";、別のオブジェクトを指すように参照を変更しています(を行ったときと同様ですt2 = t1;

Test2番目のケースで行ったのと同じことを行うと、同じ結果が得られます(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です。ただし、変更可能なクラスは、変更するために何もしなければ、まったく同じように機能します。

于 2012-06-13T18:04:01.720 に答える
3

t1とt2の両方が同じオブジェクトを参照しているため、オブジェクト状態のチャネは両方に影響します。

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

于 2012-06-13T09:17:02.507 に答える
2

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


編集

t2とt1の両方が同じオブジェクトを指しているのでしょうかTest t2 = t1;、それともそれぞれが独自のオブジェクトを持っているのでしょうか。

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

ただし、これをStringsで実行してs1 = "1" ;から、s1が別のStringオブジェクトを指すようにするようなことを行う場合。あなたはそれを言葉で考えることができますs1 = new String(1);

于 2012-06-13T09:18:17.497 に答える
1

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

ただし、Stringには、Testで行うように設定できるフィールドがないため、基本的に同じテストを行うことはできません。したがって、コードをTestオブジェクトからStringオブジェクトに移植する方法はありません。

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

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

t2の値はまだ12です

于 2012-06-13T09:20:43.747 に答える
0

例としてStringBuilderを使用すると、少しわかりやすくなります。次の例は、値の代わりに参照を使用するだけのオブジェクト割り当てを示しています。

{StringBuilder str = new StringBuilder();

    str.append("GFG");

    StringBuilder str1 = str;

    str.append("tail");
    // output: str1 = GFGtail str = GFGtail
    System.out.println("str1 = " + str1.toString() + " str = " + str.toString());  

}

于 2020-05-07T02:46:59.187 に答える
0

javaは文字列リテラルの概念を使用しているためです。5つの参照変数があり、すべてが1つのオブジェクト「0」を参照しているとします。1つの参照変数がオブジェクトの値を変更すると、すべての参照変数に影響します。これが、文字列オブジェクトがJavaで不変である理由です。

于 2020-10-20T06:33:19.563 に答える