深入 JAVA对象的复制与比较
2009-03-10 13:40
302 查看
1.对象的复制
2.clone()的使用
3.对象实例的比较
////////////////////
//
/////////////////////
1.对象的复制
String str1 = "This is a string!" //这里是 "对象引用" 的复制
String str2 = new String(str1); //这里是 "对象实例" 的复制
浅复制: 只复制复合对象本身.
深复制: 除了复制复合对象本身, 还复制了复合对象的引用的对象实例.
例如:
class Pupil{
public Pupil(String sno, String name, int age){
this.sno = new String(sno);
this.name = new String(name);
this.age = age;
}
public String getSno() {
return sno;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String sno;
private String name;
private int age;
}
public class CopyDemo {
public static Pupil[] shallowCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//此时newClass 与aClass 指向同一块内存
for(int i=0; i
newClass[i] = aClass[i];
return newClass;
}
public static Pupil[] deepCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//此时newClass 与aClass 的相应sno , name 指向同一块内存
for(int i=0; i
String sno = aClass[i].getSno();
String name = aClass[i].getName();
int age = aClass[i].getAge();
newClass[i] = new Pupil(sno, name, age);
}
return newClass;
}
public static Pupil[] deeperCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//完全的复制
for(int i=0; i
String sno = new String(aClass[i].getSno());
String name = new String(aClass[i].getName());
int age = aClass[i].getAge();
newClass[i] = new Pupil(sno, name, age);
}
return newClass;
}
}
2.clone()的使用
* Object.clone()
* Cloneable 接口
* CloneNotSupportedException
a. 使用Object.clone 进行复制
两个必须条件:
1.一定要将重定义后的clone() 方法定义为公有方法(在Object 类中, 它是受保护的成员, 不能直接使用)
2.该后代类声明实现接口 Cloneable 接口(当类实现该接口, 其任何子类也会继承该接口), 该接口实际上没有任何
内容, 只是一个标识, 标志实现该接口的类提供clone() 方法.(这是接口的一种非典型用法)
public class Fraction implements Cloneable {
public Object clone() {
try{
return super.clone(); //call protected method
} catch (CloneNotSupportedException e) {
return null;
}
}
//other methods ...
}
b.重写Object.clone()
例如对 private char[] cb; character buffer 进行复制
// add in class Cirbuf
public Object clone() {
try{
Cirbuf copy = (Cirbuf)super.clone();
copy.cb = (char[])cb.clone();
return copy;
}catch (CloneNotSupportedException e){
throw new InternalError(e.toString());
}
}
c.复制数组
数组是在方法调用重以引用的形式传递的对象. 下述情况下非常适合引用来传递数组:
*正在接收的方法不修改数组
*正在调用的方法不必关心是否修改数组
*正在调用的方法想要得到数组中的修改结果
否则, 就应该在方法调用中传递数组对象的副本. 只需调用 arrObj.clone() 方法即可完成数组arrObj 的复制操作. 随后将该数组副本强制转换为其正确类型:
(type[])arrObj.clone();
System.arraycopy 方法提供一种用于在数组间复制多个元素的有效方式.
System.arraycopy(source, i, target, j, len)
3.对象实例的比较
例如:
Pupil p1 = new Pupil("99184001", "zhang3", 18);
Pupil p2 = new Pupil("99184001", "zhang3", 18);
a. "=="
if(p1 == p2)...
此次测试的是对象引用, 其结果肯定是false, 只要两个对象引用不是互为别名就不会相等.
b. 浅比较 false
if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()
&& p1.getAge() == p2.getAge()) ...;
c. 深比较 true[/code]
if(p1.getSno().equals(p2.getSno()) && p1.getName().equals(p2.getName())
&& p1.getAge() == p2.getAge()) ...;[/code]
JAVA API 的跟类Object 也提供了equals() 方法, 但它只是比较两个对象引用, 而非比较两个对象实例.
不管怎样, 如果需要比较Pupil 类的对象(例如要将它们放入对象容器), 应该为Pupil 类重定义equals() 方法:
public boolean equals(Object otherobj) {
//检查otherobj 是否为空
if(otherobj == null) return false;
//检查otherobj 是否就是当前对象
if(otherobj == this) return true;
//检查otherobj 是否具有正确的类型, 即检查是否可与当前对象比较
if(!(otherobj instanceof Pupil)) return false;
//将otherobj 转换为Pupil 类的对象引用
Pupil tmpObj = (Pupil)otherobj;
//关于学生是否相等的逻辑检查
if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)
&& age == tmpObj.age) return true;
return false;
}
JAVA API 所提供的每个类几乎都提供了采用深比较策略的equals() 方法, 例如String 类equals() 方法. 一般来说, 用户自己定义的类也应当提供合适的equals() 方法, 特别是当程序要将其对象放入JAVA API 所提供的对象容器类的时候.
按照约定, 任何类所提供的equals() 方法所实现的相等比较应该是等价关系, 即满足自反性, 对称性和传递性. 另外一个类重定义了equals() 方法, 也应该重定义相应hashCode() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外.
2.clone()的使用
3.对象实例的比较
////////////////////
//
/////////////////////
1.对象的复制
String str1 = "This is a string!" //这里是 "对象引用" 的复制
String str2 = new String(str1); //这里是 "对象实例" 的复制
浅复制: 只复制复合对象本身.
深复制: 除了复制复合对象本身, 还复制了复合对象的引用的对象实例.
例如:
class Pupil{
public Pupil(String sno, String name, int age){
this.sno = new String(sno);
this.name = new String(name);
this.age = age;
}
public String getSno() {
return sno;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String sno;
private String name;
private int age;
}
public class CopyDemo {
public static Pupil[] shallowCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//此时newClass 与aClass 指向同一块内存
for(int i=0; i
newClass[i] = aClass[i];
return newClass;
}
public static Pupil[] deepCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//此时newClass 与aClass 的相应sno , name 指向同一块内存
for(int i=0; i
String sno = aClass[i].getSno();
String name = aClass[i].getName();
int age = aClass[i].getAge();
newClass[i] = new Pupil(sno, name, age);
}
return newClass;
}
public static Pupil[] deeperCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//完全的复制
for(int i=0; i
String sno = new String(aClass[i].getSno());
String name = new String(aClass[i].getName());
int age = aClass[i].getAge();
newClass[i] = new Pupil(sno, name, age);
}
return newClass;
}
}
2.clone()的使用
* Object.clone()
* Cloneable 接口
* CloneNotSupportedException
a. 使用Object.clone 进行复制
两个必须条件:
1.一定要将重定义后的clone() 方法定义为公有方法(在Object 类中, 它是受保护的成员, 不能直接使用)
2.该后代类声明实现接口 Cloneable 接口(当类实现该接口, 其任何子类也会继承该接口), 该接口实际上没有任何
内容, 只是一个标识, 标志实现该接口的类提供clone() 方法.(这是接口的一种非典型用法)
public class Fraction implements Cloneable {
public Object clone() {
try{
return super.clone(); //call protected method
} catch (CloneNotSupportedException e) {
return null;
}
}
//other methods ...
}
b.重写Object.clone()
例如对 private char[] cb; character buffer 进行复制
// add in class Cirbuf
public Object clone() {
try{
Cirbuf copy = (Cirbuf)super.clone();
copy.cb = (char[])cb.clone();
return copy;
}catch (CloneNotSupportedException e){
throw new InternalError(e.toString());
}
}
c.复制数组
数组是在方法调用重以引用的形式传递的对象. 下述情况下非常适合引用来传递数组:
*正在接收的方法不修改数组
*正在调用的方法不必关心是否修改数组
*正在调用的方法想要得到数组中的修改结果
否则, 就应该在方法调用中传递数组对象的副本. 只需调用 arrObj.clone() 方法即可完成数组arrObj 的复制操作. 随后将该数组副本强制转换为其正确类型:
(type[])arrObj.clone();
System.arraycopy 方法提供一种用于在数组间复制多个元素的有效方式.
System.arraycopy(source, i, target, j, len)
3.对象实例的比较
例如:
Pupil p1 = new Pupil("99184001", "zhang3", 18);
Pupil p2 = new Pupil("99184001", "zhang3", 18);
a. "=="
if(p1 == p2)...
此次测试的是对象引用, 其结果肯定是false, 只要两个对象引用不是互为别名就不会相等.
b. 浅比较 false
if(p1.getSno() == p2.getSno() && p1.getName() == p2.getName()
&& p1.getAge() == p2.getAge()) ...;
c. 深比较 true[/code]
if(p1.getSno().equals(p2.getSno()) && p1.getName().equals(p2.getName())
&& p1.getAge() == p2.getAge()) ...;[/code]
JAVA API 的跟类Object 也提供了equals() 方法, 但它只是比较两个对象引用, 而非比较两个对象实例.
不管怎样, 如果需要比较Pupil 类的对象(例如要将它们放入对象容器), 应该为Pupil 类重定义equals() 方法:
public boolean equals(Object otherobj) {
//检查otherobj 是否为空
if(otherobj == null) return false;
//检查otherobj 是否就是当前对象
if(otherobj == this) return true;
//检查otherobj 是否具有正确的类型, 即检查是否可与当前对象比较
if(!(otherobj instanceof Pupil)) return false;
//将otherobj 转换为Pupil 类的对象引用
Pupil tmpObj = (Pupil)otherobj;
//关于学生是否相等的逻辑检查
if(sno.equals(tmpObj.sno) && name.equals(tmpObj.name)
&& age == tmpObj.age) return true;
return false;
}
JAVA API 所提供的每个类几乎都提供了采用深比较策略的equals() 方法, 例如String 类equals() 方法. 一般来说, 用户自己定义的类也应当提供合适的equals() 方法, 特别是当程序要将其对象放入JAVA API 所提供的对象容器类的时候.
按照约定, 任何类所提供的equals() 方法所实现的相等比较应该是等价关系, 即满足自反性, 对称性和传递性. 另外一个类重定义了equals() 方法, 也应该重定义相应hashCode() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外.
相关文章推荐
- 深入Java对象的比较
- 深入Java对象的比较
- 深入java的equals方法,怎么比较两个对象的内容是否相等?对象的内容指的是什么?
- Java进阶:深入equals方法对象相等比较
- 深入Java对象的比较
- 深入java对象复制的分析
- Java基础(11):字符串—深入理解String对象和比较符==和equals的不同
- 深入Java对象的比较
- 深入Java对象的比较
- java中两个对象间的属性值复制,比较,转为map方法实现
- 深入Java对象的比较
- java hasmap对象的深复制实现:字节码复制和对象序列化成字符串复制比较。
- 深入理解Java对象序列化
- 深入理解Java对象的创建过程:类的初始化与实例化
- js原型对象与Java类的比较
- 深入理解Java对象序列化
- 深入理解Java对象的创建过程:类的初始化与实例化
- JAVA 复制对象时为什么要用克隆clone()而不用“=”的原因
- java复制对象
- 【面试宝典】从对象深入分析 Java 中实例变量和类变量的区别