今天工作时遇到这样一个问题。类B继承类A。从一个方法中得到的返回值的类型是A,然而我要显示在界面中需要的是类B。
代码段1如下:
public class A{
private String s;
}
public class B extends A{
private int i;
}
private A someMethod(){
A a = new A();
a.setS("Hello World");
return a;
}
那么问题来了,如何把对象a的成员们的值复制到对象b的同名成员中呢?
当时首先想到的就是用cast。比如下面这样
代码段2:
A aa = someMethod();
B bb = new B();
bb = (B) aa;
这段代码在编译时是没有问题的。但是在运行时就会抛出异常如下:
java.lang.ClassCastException
为什么呢?
在java中使用cast是一定要小心的。使用bb = (B) aa;这种类型转换相当于告诉java,相信我没错的,哥很专业,aa一定是类B,不会有问题的。
然而事实上aa并不是B。
从内存的角度上讲(如图1),我们首先定义了aa,其中有一个成员 s("Hello World")。而后我们定义类bb,其有一个成员s(null),及一个成员i(0)。
最后我们尝试给bb赋值,将其指向堆内存中的aa。然而bb中的i本来指向堆内存中的一个1,在我们将bb指向aa的堆内存地址时,i无所适从,因为aa的堆内存地址中不存在i的位置。
所以bb = (B) aa; 一定会抛出异常。
如何解决这个问题?如何把aa里已经存在的值赋值到bb中呢?
方法1: copyProperties(Object source,Object target)
在我的项目里我们用了spring,其中有个一类,BeanUtils,其有一个方法copyProperties(),它可以把所有匹配的成员复制。
代码如下:
A aa = someMethod();
B bb = new B();
BeanUtils.copyProperties(aa, bb);
这个方法并不需要一定是子类与父类的赋值,只要有同名的成员变量即可。
方法2: 利用constructor()
首先在A类中写一个constructor
public class A {
private String s;
public A(String s) {
this.s = s;
}
}
然后在B类中使用A的构造方法。
public class B extends A{
public B(A a) {
super(a.getS());
}
private int i;
}
A aa = someMethod();
B bb = new B(aa);
bb.setI(1);//this works
方法3: 利用mapper手动赋值
这个方法比较简单就不写sample了。
Ps:技术层面的不足欢迎指出,我一定理清并且改正。
Ps:如果有人看的话。