看了网上的一些资料,说一个类如要可以拷贝,需要自己另外重写clone(),但是以下一个程序并没有重写clone()仍然可以拷贝。这是为什么呢?还有为什么一定要声明main()方法可能会抛出一个错误?
public class Student implements Cloneable
{
private int id;
private String name;
public Student()
{
this.id = 744;
this.name = "FL";
}
public Student(int id, String name)
{
this.id = id;
this.name = name;
}
public boolean equals(Object obj)
{
return this.id == ((Student)obj).id;
}
public String toString()
{
return "Student id : " + id + " Name " + name;
}
public static void main(String[] args)
throws CloneNotSupportedException //这里为什么一定得写
{
Student s1 = new Student(101, "WangQiang");
Student s2 = (Student)s1.clone();
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
}
}
public class Student implements Cloneable
{
private int id;
private String name;
public Student()
{
this.id = 744;
this.name = "FL";
}
public Student(int id, String name)
{
this.id = id;
this.name = name;
}
public boolean equals(Object obj)
{
return this.id == ((Student)obj).id;
}
public String toString()
{
return "Student id : " + id + " Name " + name;
}
public static void main(String[] args)
throws CloneNotSupportedException //这里为什么一定得写
{
Student s1 = new Student(101, "WangQiang");
Student s2 = (Student)s1.clone();
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
}
}
解决方案 »
- painComponent(Graphics g)
- 静态语句块在继承中的顺序问题
- 如何获得成对的数据,并打印?
- db2关于resultset自动关闭问题
- 我想写个javabean 修改数据库记录的,该怎样写,请大家给个例子,这是我的jsp的代码
- 在java中, 对一个磁盘里的所有文件进行遍历 ,把所有文件存放到一个缓冲区中,请问该如何实现???/谢谢
- 为什么调试时按F5不能进入方法体中
- 还是不能运行呀!
- 乱码问题 散分400
- 新手问题:关于new的问题?
- 【新手学java】jdk1.6+myeclipse6.5+sqlserver2000数据库连接问题
- JMF的效率怎么样?可以和c++媲美吗?java有流媒体服务器吗?
Student s2 = (Student)s1.clone();
谁说要拷贝?
Student s2 = s1;直接这样
Main
public static void main(String[] args)可以这样写 不一定要抛异常
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
你的Student 实现了该接口,不需要在thow exception 了。
而且 Object的 clone方法是支持大多数复制的。所以你代码没问题。
所以需要抛出CloneNotSupportedException 异常。
Student student1 = new Student(101, "WangQiang");
Student student2 = student1 ;System.out.println(student2 == student1) ;
不就是一个对象吗?
(1) 检查执行此方法的当前类有没有应用Clonable接口,如果没有,抛出CloneNotSupportedException异常。
(2) 如果当前类有应用Clonable接口,则为当前类创建一个新对象(所以s1==s2为false),并将原对象中的所有字段进行一次浅层拷贝(通过赋值进行)。这就是你的程序没有写clone()方法但“看起来”仍然可以克隆的原因。为什么是“看起来”下面会解释。3) 为什么应用了Cloneable接口的类通常还必须重写一个public的clone()方法?这里有两个原因:
(1) 如果不重写,由于Object.clone()是proteced属性,所以这个clone()方法将无法在外部被调用,更精确地说,无法在当前类之外的任何地方调用。这样就使得克隆失去了用武之地。LZ的例子中刚好是在Student类中调用s1.clone()方法,所以没有问题,但这没有实用价值。
(2) Object.clone()毕竟只是提供了浅层拷贝,对于基本类型的字段,可以说它成功克隆了。但对于对象型字段,它并没有实现克隆的功能,仅仅做了一个赋值。试运行一下下面的代码就会更清楚了:public class Student implements Cloneable
{
private int id;
private String name;
public StringBuffer sb = new StringBuffer(""); public Student() {
this.id = 744;
this.name = "FL";
} public Student(int id, String name) {
this.id = id;
this.name = name;
} public boolean equals(Object obj) {
return this.id == ((Student) obj).id;
} public String toString() {
return "Student id : " + id + " Name " + name;
} public static void main(String[] args) throws CloneNotSupportedException // 这里为什么一定得写
{
Student s1 = new Student(101, "WangQiang");
Student s2 = (Student) s1.clone();
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2); s1.sb.append("s1's string");
System.out.println("s2.sb's value = " + s2.sb.toString());
System.out.println(s1.sb==s2.sb);
}
}
4) 运行时是否抛出CloneNotSupportedException跟你是否重写了clone()方法没有关系,只跟是否应用了Cloneable接口有关系。5) 重写clone()方法不一定需要应用Cloneable接口,因为只有执行Object.clone()方法才会做这个检查。但如果clone()方法中用到了super.clone(),那就必须应用Cloneable接口,原因不难理解。6)应用Cloneable接口的好处在于,它可以允许你安全地调用super.clone(),从而快速地产生一个浅拷贝,之后只需要在重写的公共clone()方法中修改必须修改的字段,如那些不允许共享实例的对象。