Java 15で2nd previewとなっているRecordにcloneメソッドを実装し、deep copyできるようにします。
特にこれといって使う場面は浮かびませんが、いつか使うかもしれないので備忘録に。
ポイントはsuper.clone()
を使わずにコンストラクタでcloneを作ることくらいです。
環境
Java 15(Oracle Open JDK)
IntelliJ IDEA Community版
Windows
※IntelliJでRecordを使うための設定は以下を参考にしてください(手前味噌ですが)。
https://qiita.com/tora_kouno/items/58eff9f4eb99a941fd41
実装
clone実装前
ExampleRecord.java
public record ExampleRecord(String name, int age, ExampleDto dto) {
}
ExampleDto.java
public class ExampleDto {
private String name;
private int age;
private NodeDto node;
// setter, getter, toStringは省略
}
NodeDto.java
public class NodeDto {
private String name;
// setter, getter, toStringは省略
}
clone実装後
ExampleRecord.java
public record ExampleRecord(String name, int age, ExampleDto dto) {
@Override
public ExampleRecord clone() {
try {
return new ExampleRecord(this.name, this.age, this.dto.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
ExampleDto.java
public class ExampleDto implements Cloneable {
private String name;
private int age;
private NodeDto node;
// setter, getter, toStringは省略
@Override
public ExampleDto clone() throws CloneNotSupportedException {
ExampleDto copy = (ExampleDto) super.clone();
copy.node = this.node.clone();
return copy;
}
}
NodeDto.java
public class NodeDto implements Cloneable {
private String name;
// setter, getter, toStringは省略
@Override
public NodeDto clone() throws CloneNotSupportedException {
return (NodeDto) super.clone();
}
}
試す
実装
Main.java
public class Main {
public static void main(String[] args) {
ExampleDto dto = new ExampleDto();
NodeDto nodeDto = new NodeDto();
nodeDto.setName("node1");
dto.setNode(nodeDto);
dto.setName("dto1");
dto.setAge(1);
ExampleRecord exampleRecord = new ExampleRecord("record1", 2, dto);
System.out.println("exampleRecord:"+exampleRecord);// 1
dto.setName("dto2");
nodeDto.setName("node2");
System.out.println("exampleRecord:"+exampleRecord);// 2
ExampleRecord clone = exampleRecord.clone();
System.out.println("clone:"+clone);// 3
dto.setName("dto3");
nodeDto.setName("node3");
System.out.println("clone:"+clone);// 4
}
}
実行結果
1.
exampleRecord:ExampleRecord[name=record1, age=2, dto=ExampleDto{name='dto1', age=1, node=NodeDto{name='node1'}}]
2.
exampleRecord:ExampleRecord[name=record1, age=2, dto=ExampleDto{name='dto2', age=1, node=NodeDto{name='node2'}}]
3.
clone:ExampleRecord[name=record1, age=2, dto=ExampleDto{name='dto2', age=1, node=NodeDto{name='node2'}}]
4.
clone:ExampleRecord[name=record1, age=2, dto=ExampleDto{name='dto2', age=1, node=NodeDto{name='node2'}}]
1->2ではDtoの中身が変わってしまっていますが、3->4では別インスタンスであるためdto.setName("dto3");
やnodeDto.setName("node3");
の影響を受けず、問題なくcloneされていることがわかります。