クローン作成
割り当てメソッドのあるクラスオブジェクトは可変オブジェクトと呼ばれ、割り当てメソッドのないクラスオブジェクトは不変オブジェクトと呼ばれます。
//因为Object是所有其他类的超类,所以任意方法的实现中都可以含有调用,但是类的客户不能调用clone()
//除非类重写了且将它声明为公有的。对对象进行复制可能很费时间。。。
protected Object clone() throws CloneNotSupportedException;
インターフェイスCloneableには宣言メソッドはありません。クラスがclone()を実装していることを示すためにのみ使用されます。
public interface Cloneable(){
}
//空的Cloneable接口不是一个典型的接口,实现它的类表示,它提供了一个公有的clone方法。因为java提供了clone()方法的默认实现,故将它放在Object类中,没有放在Cloneable接口中。但因为不想让每一个类都自动拥有一个公有的clone()方法,所以clone()方法是一个保护方法。
public class Name implements Cloneable{
private String first;
private String last;
public Object clone(){
Name theCopy = null;
try {
theCopy = (Name)super.clone();//必须调用超类的方法
}catch (CloneNotSupportedException e){
throw new Error(e.toString());//System.err.println("Name cannot clone: "+e.toString());
}
return theCopy;//隐式转换
}
public Name(){
}
public Name(String firstName,String lastName){
first = firstName;
last = lastName;
}
public void setName(String firstName,String lastName){
setFirst(firstName);
setLast(lastName);
}
public String getName(){
return toString();
}
public void setFirst(String firstName){
first = firstName;
}
public String getFirst(){
return first;
}
public void setLast(String lastName){
last = lastName;
}
public String getLast(){
return last;
}
public void giveLastNameTo(Name aName){
aName.setLast(last);
}
@Override
public String toString() {
return "Name{" +
"first='" + first + '\'' +
", last='" + last + '\'' +
'}';
}
}
コピーする方法は???浅いコピーと深いコピー
データフィールドがオブジェクトの場合、2つの方法があります。
(1)オブジェクトへの参照をコピーし、共有オブジェクトのクローンを作成できます。浅いコピー
(2)オブジェクト自体をコピーします。これはディープコピーと呼ばれます。
Objectのclone()メソッドは、浅いクローンを返します。クラスNameには、最初と最後のデータメンバーがあります。これはStringのインスタンスです。各フィールドの文字への参照。Nameのcloneメソッドが呼び出されたときにコピーされないのは、これらの参照です。。。
Nameクラスの場合、Stringインスタンスは不変であるため、浅いクローン作成で十分です。したがって、Nameのインスタンスとそれが同じ文字列を共有するようにすると、文字列は変更できないため、問題にはなりません。。。
class test{
public static void main(String[] args) {
Name a = new Name("haixia","zhang");
Name b = (Name)a.clone();//b是a的浅克隆
System.out.println(a+" "+b);
b.setLast("lu");
System.out.println(a+" "+b);
}
}
!!!クラスにデータフィールドとして可変オブジェクトがある場合、浅いクローン作成は適切ではなく、オブジェクトのクローン作成時にそれらの参照を単純にコピーすることはできません。
これで、NameのインスタンスがStudentクラスのメンバーとして使用されます。Nameにはメソッドが設定されているため、ディープクローンが必要です。
public class Student implements Cloneable{
private Name fullname;
private String id;
public Object clone(){
Student theCopy = null;
try {
theCopy = (Student)super.clone();
}catch (CloneNotSupportedException e){
throw new Error(e.toString());
}
theCopy.fullname = (Name)fullname.clone();
return theCopy;
}
public Student(){
fullname = new Name();
id = "";
}
public Student(Name studentName,String studentId){
fullname = studentName;
id = studentId;
}
public void setStudent(Name studentName,String studentId){
setName(studentName);
setId(studentId);
}
public void setName(Name studentName){
fullname = studentName;}
public Name getName(){
return fullname;}
public void setId(String studentId){
id = studentId;}
public String getId(){
return id;}
@Override
public String toString() {
return "Student{" +
"fullname=" + fullname +
", id='" + id + '\'' +
'}';
}
}
まとめ;各
publicclone()メソッドでは、通常、次のタスクが実行されます。1。スーパークラスのcloneメソッドを呼び出すためにsuper.clone()を記述します
。2。呼び出しをtryブロックに入れ、catchブロックを次のように記述します。可能な処理
パブリックclone()メソッドが呼び出された場合、例外CloneNotSupportedExceptionをスキップできます。
3.可能であれば、super.clone()によって返されたオブジェクトの変数データのクローンを作成します。4
。クローンを返します。
public class CollegeStudent extends Student{
private int year;
private String degree;
public Object clone(){
//因为CollegeStudent对象的数据域是基本类型值和不可变数据对象,故它们不需要被克隆。
CollegeStudent theCopy = (CollegeStudent)super.clone();
return theCopy;
}
@Override
public String toString() {
return super.toString() + ", " + degree + ", " + year;
}
public CollegeStudent(){
super();
year = 0;
degree = ""
}
}