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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Java

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

Q&A

解決済

2回答

3603閲覧

参照型においてのclone()メソッドの深いコピーについて

toaru

総合スコア1

Java

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

0グッド

1クリップ

投稿2020/05/09 12:58

前提・実現したいこと

画面表示
コピー後
p1Person [name=name1, age=21, item=Item [name=アイテム1]]
p2Person [name=name1, age=21, item=Item [name=アイテム1]]
アイテム変更後
p1Person [name=name1, age=23, item=Item [name=アイテム2]]
p2Person [name=name1, age=21, item=Item [name=アイテム1]]
を目指し、
cloneメソッドをなるべく少ない行で完成させようと考えています。

Personクラス内にclone()メソッドを記述して、p1とp2を作ります。

発生している問題・エラーメッセージ

問題:
Personフィールドの
private String name;
private int age;
に対しては
「result = (Person)super.clone();」で対応できるのですが、
参照型のItem itemに対して上手く深いコピーができません。
「result.item = (Item)this.item.clone();」

Exception in thread "main" java.lang.Error: Unresolved compilation problem: メソッド clone() は型 Object で不可視です at Person.clone(Person.java:27) at Main.main(Main.java:10)

該当のソースコード

public class Main {

public static void main(String[] args) { Item item = new Item("アイテム1"); Person p1 = new Person("name1", 21, item); Person p2 = p1.clone(); System.out.println("コピー後"); System.out.println("p1" + p1); System.out.println("p2" + p2); item.setName("アイテム2"); p1.setAge(23); System.out.println("アイテム変更直後"); System.out.println("p1" + p1); System.out.println("p2" + p2); }

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
public class Person implements Cloneable {
private String name;
private int age;
private Item item;

public Person() {} public Person(String name, int age, Item item){ this.name = name; this.age = age; this.item = item; } public Person clone() { Person result = null; try { //この一行で全てのフィールドをコピーする result = (Person)super.clone(); //フィールドに参照型を含む場合 //[メソッド clone() は型 Object で不可視です]となってしまう。 result.item = (Item)this.item.clone(); }catch(CloneNotSupportedException e) { e.printStackTrace(); } return result; } //setter,getterは省略 public String toString() { return "Person [name =" + name + ", age=" + age + ", item=" + item + "]"; }

}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
public class Item {
private String name;

public Item() {} public Item(String name) { this.name = name; }

     public String toString() {
return "Item [name =" + name + "]";
}
//setter,getterは省略
}

言語:java

試したこと

妥協案として
Item itemCopy = new Item();
itemCopy = (Item)this.item;       
result.item =itemCopy;
で、Itemをインスタンス化しましたが
Itemクラス内のString nameをprivateにすると
うまく行きませんでした。

補足情報(FW/ツールのバージョンなど)

ツール:eclpipse Version: 2020-03 (4.15.0)

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

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

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

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

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

guest

回答2

0

ベストアンサー

Itemでもcloneをオーバーライドしてください。
Objectクラスのcloneメソッドはprotectedのため、継承先でなければ使えません(同パッケージ内でも使えるが、Objectが属するパッケージであるjava.langパッケージの中で使う状況はありえない)。

投稿2020/05/09 19:30

swordone

総合スコア20669

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

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

toaru

2020/05/10 01:30

ご回答ありがとうございます。 Itemクラスでもclone()メソッドをオーバーライドしてみたのですが、うまくいきません。 お手数ですが、ソースコードのチェックもお願いしたい所存です。 CloneNotSupportedExceptionが発生してしまい、表示例がnullとなってしまいます。 「コピー後 p1Person [name =name1, age=21, item=Item [name =アイテム1]] p2Person [name =name1, age=21, item=null] アイテム変更直後 p1Person [name =name1, age=23, item=Item [name =アイテム2]] p2Person [name =name1, age=21, item=null] 」 itemのclone()メソッドを public Item clone() { Item result = null; try { result = (Item)super.clone(); result = (Item)this.clone(); }catch(CloneNotSupportedException e) { e.printStackTrace(); } return result; } のようにオーバーライドしたのですが、不審な点はありますか?
swordone

2020/05/10 01:46

もちろんCloneableを実装しててす。
toaru

2020/05/10 02:30

ありがとうございます。 解決できました!
guest

0

cloneメソッドをなるべく少ない行で完成させようと考えています。

java.io.Serializableインタフェースを実装して、オブジェクトを複製する。かな。

java

1import org.junit.Test; 2import java.io.*; 3 4public class xxHoge { 5 6 public static class Person implements Serializable { 7 private String name; 8 private int age; 9 private Item item; 10 11 public Person() { 12 } 13 14 public Person(String name, int age, Item item) { 15 this.name = name; 16 this.age = age; 17 this.item = item; 18 } 19 20 public Person clone() { 21 try ( 22 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 23 ObjectOutputStream oos = new ObjectOutputStream(baos);) { 24 oos.writeObject(this); 25 oos.close(); 26 try ( 27 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 28 ObjectInputStream ois = new ObjectInputStream(bais);) { 29 return (Person) ois.readObject(); 30 } 31 } catch (Exception e) { 32 throw new RuntimeException(e); 33 } 34 } 35 36 public String toString() { 37 return "Person [name =" + name + ", age=" + age + ", item=" + item + "]"; 38 } 39 40 public void setAge(int value) { 41 age = value; 42 } 43 } 44 45 public static class Item implements Serializable { 46 private String name; 47 48 public Item() { 49 } 50 51 public Item(String name) { 52 this.name = name; 53 } 54 55 public String toString() { 56 return "Item [name =" + name + "]"; 57 } 58 59 public void setName(String value) { 60 name = value; 61 } 62 } 63 64 @Test 65 public void hoge() throws Exception { 66 Item item = new Item("アイテム1"); 67 Person p1 = new Person("name1", 21, item); 68 Person p2 = p1.clone(); 69 70 System.out.println("コピー後"); 71 System.out.println("p1" + p1); 72 System.out.println("p2" + p2); 73 74 item.setName("アイテム2"); 75 p1.setAge(23); 76 System.out.println("アイテム変更直後"); 77 System.out.println("p1" + p1); 78 System.out.println("p2" + p2); 79 } 80} 81

text

1コピー後 2p1Person [name =name1, age=21, item=Item [name =アイテム1]] 3p2Person [name =name1, age=21, item=Item [name =アイテム1]] 4アイテム変更直後 5p1Person [name =name1, age=23, item=Item [name =アイテム2]] 6p2Person [name =name1, age=21, item=Item [name =アイテム1]]

外に切り出して、こんなの用意しとくのもよろしいかと。

java

1import java.io.*; 2 3public class Clones { 4 public static <A extends Serializable> A clone(final A source) { 5 if(source == null) return source; 6 7 try ( 8 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 9 ObjectOutputStream oos = new ObjectOutputStream(baos);) { 10 oos.writeObject(source); 11 oos.close(); 12 try ( 13 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 14 ObjectInputStream ois = new ObjectInputStream(bais);) { 15 return (A) ois.readObject(); 16 } 17 } catch (Exception e) { 18 throw new RuntimeException(e); 19 } 20 } 21}

java

1 @Test 2 public void hoge2() throws Exception { 3 Item item = new Item("アイテム1"); 4 Person p1 = new Person("name1", 21, item); 5 Person p2 = Clones.clone(p1);

投稿2020/05/09 13:21

編集2020/05/09 22:14
shiketa

総合スコア4061

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

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

toaru

2020/05/10 01:21

ご回答ありがとうございます。 じっくり精査してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問