Java: 如何将克隆的对象转换为其原始子类?
Java: How do I cast a cloned object to it's original subclass?
想象超class答:
public class A {
private int x;
A(int x){
this.x = x;
}
public int getX() {
return x;
}
}
它是 2 个子classes B 和 C:
public class B extends A{
private int y = 2;
B(int x){
super(x);
}
}
public class C extends A{
private int y = 3;
B(int x){
super(x);
}
}
现在想象一个全部继承 class A 的对象列表。我想遍历该列表并克隆每个对象并将其转换为原始子class(B 或 C) .这就是我尝试这样做的方式:
public static void main(String args[]) {
ArrayList<A> aList = new ArrayList<A>();
aList.add(new B(5));
aList.add(new C(6));
ArrayList<A> aClones = new ArrayList<A>();
for(A a : aList) {
A aNew = new A(a.getX());
a.getClass().cast(aNew);
aClones.add(aNew);
}
}
但这给了我一个错误,说我不能将 A 转换为 B。如果事先不知道我正在处理的对象的子类型,我如何能够实现这一点?我可以在 for 循环中为每种类型的 subclass 做一个 if 语句来检查 a
是否是该 subclass 的一个实例,然后简单地创建一个特定的新实例subclass 并以这种方式克隆它。然而,在我的情况下,除了 B 和 C 之外,还有更多的 subclasses,而且可能还会有更多。我不希望 for 循环包含有关 A 的现有子 class 的任何知识。这可能吗?
您应该使用子class 的构造函数克隆它。
否则它将是无法转换为 C 或 B 的超级 class A 的类型
参见例如反思:http://tutorials.jenkov.com/java-reflection/constructors.html
或者最好使用克隆功能。
https://en.m.wikipedia.org/wiki/Clone_(Java_method)
那应该容易得多。
你可以这样做
for(A a : aList) {
A anew;
if (a.getClass() == A.class) anow = new A(a.getX());
else if (a.getClass() == B.class) anow = new B(a.getX());
else if (...
}
这不能按照你写的方式完成。
原因很简单:B
和C
与A
有是关系,但是A
与 B
或 C
没有相同的 is-a 关系。
这主要是因为您正在尝试使用 superclass 来迭代来描述所有内容。
for(A a : aList) { }
当你迭代时,你无法通过类型推断单独知道具体的class A
实际上是。
正如预期的那样,这失败了。
a.getClass().cast(aNew);
如果不明确询问class它是什么类型,您将无法做到这一点。
这意味着如果您打算对此进行扩展,您将编写大量 instanceof
语句。
for(A a : aList) {
if(a instanceof B) {
B b = new B(a.getX());
aClones.add(b);
}
if(a instanceof C) {
C c = new C(a.getX());
aClones.add(c);
}
}
想象超class答:
public class A {
private int x;
A(int x){
this.x = x;
}
public int getX() {
return x;
}
}
它是 2 个子classes B 和 C:
public class B extends A{
private int y = 2;
B(int x){
super(x);
}
}
public class C extends A{
private int y = 3;
B(int x){
super(x);
}
}
现在想象一个全部继承 class A 的对象列表。我想遍历该列表并克隆每个对象并将其转换为原始子class(B 或 C) .这就是我尝试这样做的方式:
public static void main(String args[]) {
ArrayList<A> aList = new ArrayList<A>();
aList.add(new B(5));
aList.add(new C(6));
ArrayList<A> aClones = new ArrayList<A>();
for(A a : aList) {
A aNew = new A(a.getX());
a.getClass().cast(aNew);
aClones.add(aNew);
}
}
但这给了我一个错误,说我不能将 A 转换为 B。如果事先不知道我正在处理的对象的子类型,我如何能够实现这一点?我可以在 for 循环中为每种类型的 subclass 做一个 if 语句来检查 a
是否是该 subclass 的一个实例,然后简单地创建一个特定的新实例subclass 并以这种方式克隆它。然而,在我的情况下,除了 B 和 C 之外,还有更多的 subclasses,而且可能还会有更多。我不希望 for 循环包含有关 A 的现有子 class 的任何知识。这可能吗?
您应该使用子class 的构造函数克隆它。 否则它将是无法转换为 C 或 B 的超级 class A 的类型 参见例如反思:http://tutorials.jenkov.com/java-reflection/constructors.html
或者最好使用克隆功能。 https://en.m.wikipedia.org/wiki/Clone_(Java_method)
那应该容易得多。
你可以这样做
for(A a : aList) {
A anew;
if (a.getClass() == A.class) anow = new A(a.getX());
else if (a.getClass() == B.class) anow = new B(a.getX());
else if (...
}
这不能按照你写的方式完成。
原因很简单:B
和C
与A
有是关系,但是A
与 B
或 C
没有相同的 is-a 关系。
这主要是因为您正在尝试使用 superclass 来迭代来描述所有内容。
for(A a : aList) { }
当你迭代时,你无法通过类型推断单独知道具体的class A
实际上是。
正如预期的那样,这失败了。
a.getClass().cast(aNew);
如果不明确询问class它是什么类型,您将无法做到这一点。
这意味着如果您打算对此进行扩展,您将编写大量 instanceof
语句。
for(A a : aList) {
if(a instanceof B) {
B b = new B(a.getX());
aClones.add(b);
}
if(a instanceof C) {
C c = new C(a.getX());
aClones.add(c);
}
}