質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

コピー

元のオブジェクトを破壊することなく、オブジェクトの複製を生成することをコピーと呼びます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

509閲覧

<Java>arraycopyでコピーしたものを書き換えた場合の挙動について

kytm

総合スコア11

参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

String

Stringは、ゼロ以上の文字から連続してできた文字の集合を扱うデータ型です。基本的にテキストを表すために使われます。

コピー

元のオブジェクトを破壊することなく、オブジェクトの複製を生成することをコピーと呼びます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/11/20 03:00

編集2019/11/20 03:03

Java配列の参照型についての質問です。
Java2は私が作成したnameフィールドを持つクラスです。
以下コード↓↓↓
Java2[] array = {new Java2("aaa"),new Java2("bbb")};
Java2[] array2 = new Java2[];
System.arraycopy(array,0,array2,0,array.length);
array2[0].name = "ccc";
System.out.println(array[0].name);
これを実行すると"ccc"と出力されます。これは配列の中身に参照が入っているので納得できます。

しかし、Stringの場合、
String[] str = {"aaa","bbb"};
String[] s = new String[];
System.arraycopy(str,0,s,0,array.length); ---------ここを書き換える
s[0] = "ccc";
System.out.println(str[0]);
同じように配列の中身に参照が入っているのにもかかわらず"aaa"と出力され、書き換えることができません。
そして、
System.arraycopy(str,0,s,0,array.length); ←こちらの文をs = str;に書き換えて実行したところ、
str[0]は"ccc"と出力されました。なぜでしょうか?

ちなみに
String a = "a";
String b = a;
b = "c";
System.out.println(a);
これを出力すると"a"が出力されます。これはString型の特性上、bにaの参照値を代入したとしても、参照先の値をコピーしてbに新たなインスタンスが生成され、aとbは別々のインスタンスを参照しているから。というのは理解しています。

私自身がarraycopyの内部での動きをよく理解できていないのもあると思います。
ご教授よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

同じように配列の中身に参照が入っているのにもかかわらず"aaa"と出力され、書き換えることができません。

この場合、オブジェクトそのものを入れ替えているので、コピー元に影響はありません。

JavaのStringはイミュータブルであり、そもそも書替える方法が存在しません。文字列の変更はすなわちインスタンスの変更です。

投稿2019/11/20 03:14

編集2019/11/20 03:16
maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

これはString型の特性上、bにaの参照値を代入したとしても、参照先の値をコピーしてbに新たなインスタンスが生成され、aとbは別々のインスタンスを参照しているから。というのは理解しています。

そんな特性無いです。
全ての参照型のオブジェクトについて同じように動作します。

Java

1class Data { 2 int num; 3 Data(int n) { 4 num = n; 5 } 6} 7 8class Main { 9 public static void main(String[] args) { 10 { 11 Data d1 = new Data(0); 12 Data d2 = d1; 13 14 d2.num = 100; 15 System.out.println(d1.num); // => 100 16 System.out.println(d1 == d2); // => true 17 } 18 { 19 Data d1 = new Data(0); 20 Data d2 = d1; 21 22 d2 = new Data(100); 23 System.out.println(d1.num); // => 0 24 System.out.println(d1 == d2); // => false 25 } 26 } 27}

インスタンスと変数の区別は付いているでしょうか?

コメントを受けて

なぜStringをコピーした場合とJava2をコピーした場合とで挙動が変わってくるのでしょうか?

参照先のフィールドを置き換えるか、参照先自体を置き換えるかの違いです。

Java

1class Data { 2 int num; 3 Data(int n) { num = n; } 4} 5 6public class Main { 7 public static void main(String[] args) { 8 Data[] arr1 = {new Data(0), new Data(1)}; 9 Data[] arr2 = new Data[2]; 10 11 System.arraycopy(arr1, 0, arr2, 0, arr1.length); 12 arr2[0].num = 42; 13 arr2[1] = new Data(100); 14 } 15}

実行終了時の状態
実行終了時の状態

Visualize Python, Java, JavaScript, C, C++, Ruby code execution

投稿2019/11/20 03:11

編集2019/11/20 03:44
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kytm

2019/11/20 03:21

Stringクラスの中身の文字列を保持するための変数はfinalで修飾されているので後から書き換えることはできないので後からインスタンスを操作することはできないということとごちゃごちゃになっていました。 その特性がないということであれば、同じようにString型もインスタンスを生成しているのに、なぜStringをコピーした場合とJava2をコピーした場合とで挙動が変わってくるのでしょうか?
LouiS0616

2019/11/20 03:44

追記しました。
kytm

2019/11/20 05:07

Stringの配列の場合はインスタンスを新しく生成しているということですね。丁寧な図での解説ありがとうございます。
LouiS0616

2019/11/20 05:16

変数 = "hoge" は意味合い的には 変数 = new String({'h', 'o', 'g', 'e'}) と同じ※ ということを知っていれば、Stringだけ常に特別扱いされているわけでは無いことが理解できるかと思います。 --- ※ かなり誤魔化した書き方です。また、キャッシュも無視しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問