:cry:
对象的类不知道,里面属性的类型也不知道。我感觉我没救了
正常来说针对复制对象就只有这三种方式了.
1.clone (需要实现Cloneable接口)
2.序列化反序列化(需要实现Serializable接口,就是上面的流方式)
3.构造新对象,通过反射取值,填充值(我给出的办法)
再就是可能一些字节码修改工具包可能会有效.不过需要引入额外的Jar包.比较复杂了.
都有对象了,为什么不知道对象的类呢?
用反射机制吧,很轻松!
对呀,用反射。
反射可以从一个类的绝对名生成对象,例如“com.java.Sun”的串,可以实例化Sun对象,也可以执行对象中的方法。
object.getClass().getFields();可以得到对象属性。object是某对象的实例。类似的可以得其方法和名称。得到名称了也就又可以按这个名称实例化对象喽。
a.getClass().getDeclaredFields()
[code="java"] public static Object deepClone(Object obj) {
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
// 从流里读回来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
}
catch(Exception e) {
}
return obj;
}[/code]
感觉你是不是处理问题的方法不对。会出现这种情况,或是设计不当。补充说明,那个被克隆的对象,必须implements Serializable 接口。是对原来对象的克隆,属性值都是一样的,但hashcode不一样,它是新的对象了。
新手.....虽然昨天我也是..... :cry:
这段代码你可以执行一下试试.
[code="java"]import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import sun.misc.Unsafe;
public class TestClass {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) throws Exception {
TestClass tc = new TestClass();
tc.setName("oUCHxP");
//现在是一个未知类型的对象(模拟一下)
Object obj = tc;
//获取对象类型,可以看到输出是TestClass类型
Class c = obj.getClass();
System.out.println(c);
//创建此类型的空对象
Field fu = Unsafe.class.getDeclaredField("theUnsafe");
fu.setAccessible(true);
Unsafe us = (Unsafe) fu.get(null);
Object newObj = us.allocateInstance(c);
//可以看到name是空的
System.out.println("newObj.name: " + ((TestClass) newObj).getName());
//获取所有成员(包括private)的值,并拷贝到新对象中
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
//不拷贝static成员和final成员
if (Modifier.isStatic(f.getModifiers()) || Modifier.isFinal(f.getModifiers())) {
continue;
}
f.setAccessible(true);
Object fieldValue = f.get(obj);
f.set(newObj, fieldValue);
}
//再看一下新对象里的内容,private成员也被复制过来了
System.out.println("newObj.name: " + ((TestClass) newObj).getName());
}
}[/code]
这个用反射有点浪费了。。不知道这样能不能解决这个兄弟的问题[code="java"]package com.zhy.test.prototype;
public class TestClone {
/** 原型模式
* @param args
*/
public static void main(String[] args) {
try {
new TestClone().cloneObject();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
public void cloneObject() throws CloneNotSupportedException {
Person p = new Person();
Man man = new Man();
man.setSalory("111123");
p.setName("zhangfei");
p.setMan(man);
//man.setSalory("122335");//(1)
Person pp = p.getClonePerson(p);
man.setSalory("122335");//(2)
pp.setName("aa");
System.out.println("pp.getName()= " + pp.getName() + " pp.man.getSalory()= "+pp.getMan().getSalory());
System.out.println("p.getName()=" + p.getName()+" p.man.getSalory()= "+p.getMan().getSalory());
}
}
class Person implements Cloneable {
private String name = "";
private Man man;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person getClonePerson(Person p) throws CloneNotSupportedException {
Person pp = (Person) p.clone();
return pp;
}
public Man getMan() {
return man;
}
public void setMan(Man man) {
this.man = man;
}
public Object clone() throws CloneNotSupportedException{
Person p = (Person) super.clone();
p.man = this.getMan().getCloneMan(this.getMan());
return p;
}
}
class Man implements Cloneable{
private String salory = "";
public String getSalory() {
return salory;
}
public void setSalory(String salory) {
this.salory = salory;
}
public Man getCloneMan(Man man) throws CloneNotSupportedException{
Man ma = (Man)man.clone();
return ma;
}
}
[/code]
[quote="zhanghaiyangruijie"]这个用反射有点浪费了。。不知道这样能不能解决这个兄弟的问题..[/quote]
[quote="lz"]对象的类不知道,里面属性的类型也不知道。[/quote]
未必实现了Cloneable接口
一定不用反射么,用反射很容易实现的
[code="java"]
public static void main(String[] args) throws Exception {
//假设我们不知道这个对象是什么,所以用object引用,为了省事,就不写po类了,直接用了java.util.Date
Object o = new Date();
Object o2 = o.getClass().newInstance();
//遍历所有成员变量
for(Field f : o.getClass().getDeclaredFields()) {
//如果是final成员就跳过
if(Modifier.isFinal(f.getModifiers()))continue;
//设置成员变量访问权
f.setAccessible(true);
//设置成员变量内容
f.set(o2, f.get(o));
}
System.out.println(o.equals(o2));
}
[/code]
程序运行结果为true
LS的有BUG哦 :D
newInstance()调用了构造器.
构造器中可能有对final成员的初始化,而拷贝时跳过了final成员.
所以拷贝前后的两个final变量有可能值不同哦.(比如说用时间初始化)
所以拷贝时应该跳过static成员,而不应该跳过final成员.
PS:我上面给的代码也有问题.跳过条件应该只用Modifier.isStatic(f.getModifiers())