深入 JAVA对象的复制与比较
来源:百度文库 编辑:神马文学网 时间:2024/04/27 13:52:43
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; inewClass[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; iString 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; iString 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() 方法, 否则将这个类的对象放入映射对象容器时也会发生以外.
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
return newClass;
}
public static Pupil[] deepCopy(Pupil[] aClass) {
Pupil[] newClass = new Pupil[aClass.length];
//此时newClass 与aClass 的相应sno , name 指向同一块内存
for(int i=0; i
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 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虚拟机的深入研究
Java企业应用系统框架的比较与选择
常用 Java Profiling 工具的分析与比较
深入java虚拟机第20章, 线程同步-对象锁 - 日拱一卒,不求速成 - JavaEye...
JavaScript的Base对象与Body对象
复制不能复制的网页文字_这个比较全
ORACLE对象名大小写敏感性相关的深入分析
java String 对象剖析
PHP5的对象模型[5]--对象复制 - Haohappy的专栏--PHP5研究中心 - ...
java中四种操作xml方式的比较
java中四种操作xml方式的比较
解析Java对象的equals()和hashCode()的使用
深入Java初始化
Java虚拟机深入研究
深入Java初始化
Java虚拟机深入研究
深入Java字符串
[JAVA技术]61条面向对象设计的经验原则
JAVA中的指针,引用及对象的clone (developerworks)
JAVA中的指针,引用及对象的clone