Java:相同的对象,如何避免重复代码
Java: identical Objects, how to avoid duplicated code
我有一个使用外部库调用各种网络服务的项目。这个库给我这样的对象:
public static class ObjA {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
还有这个:
public static class ObjB {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
如您所见,objA 和 objB 具有相同的属性,因此,如果我必须同时使用两者,我必须复制代码:
public class myClass {
[...]
private ObjA a;
private ObjB b;
[...]
public void myClass() {
[...]
this.a = new ObjectFactory().createObjA();
this.b = new ObjectFactory().createObjB();
[...]
}
public void init() {
this.initA();
this.initB();
}
private void initA() {
this.a.setCounter(BigInteger.ZERO);
this.a.setData = "";
}
private void initB() {
this.b.setCounter(BigInteger.ZERO);
this.b.setData = "";
}
[...]
}
initA和initB相同,无法访问库代码,无法创建通用接口,如何避免重复代码?我的意思是,有可能有这样的东西吗?
private void initObj([ObjA|ObjB] obj) {
obj.setCounter(BigInteger.ZERO);
obj.setData = "";
}
谢谢!非常感谢!
附录
请注意,我无权访问底层库,因此我无法以任何方式添加修改 类、接口、wsdl 或 xsd。
同样在我看来,我是否使用 ws、jaxb 或其他库并不重要:您可以想象没有注释的 ObjA 和 ObjB,如下所示:
public static class ObjA {
protected BigInteger counter;
protected String data;
[...]
}
public static class ObjB {
protected BigInteger counter;
protected String data;
[...]
}
而问题的症结并没有改变
因为它们没有通用接口(或父接口 class?),我想要走的路是 java 反射。
像"init(Class clazz)"一样自己创建一些反射辅助方法并调用构造函数。
请记住,java 反射在大多数情况下都是不好的做法,因此请确保没有 other/better 方法可以实现您的目标。
我想您正在使用 JAXB。您可以阅读对象列表。
看到这个 post:JAXB Unmarshalling: List of objects
我假设 类 是使用某种工具为您生成的,可能是 maven cxf-codegen-plugin 等。
如果是这种情况,您需要修改 WSDL 和 XSD,以便生成令您满意的 DTO 类。
如果 WSDL 已提供给您,那么您只需按原样接受服务即可?
知道公用方法都是同名的,还可以用反射吗?
所以你会用原始反射做这样的事情:
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void initObject(Object o) throws Exception {
if (!(o instanceof ObjA)&&!(o instanceof ObjB)) return;
Method m = o.getClass().getMethod("setCounter",java.math.BigInteger.class);
m.invoke(o,BigInteger.ZERO);
m = o.getClass().getMethod("setData",java.lang.String.class);
m.invoke(o,"");
}
public static void main(final String[] args) throws Exception {
List<Object>objects = new ArrayList<Object>();
//this is like your factory method
Object o = Class.forName("ObjA").newInstance();
initObject(o);
objects.add(o);
o = Class.forName("ObjB").newInstance();
initObject(o);
objects.add(o);
}
}
如果您想使用一个库,您可以使用 JXPath 和 see docs here
但我认为就您的目的而言,原始反射可能没问题。不需要非常复杂的反射库。
我有一个使用外部库调用各种网络服务的项目。这个库给我这样的对象:
public static class ObjA {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
还有这个:
public static class ObjB {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
如您所见,objA 和 objB 具有相同的属性,因此,如果我必须同时使用两者,我必须复制代码:
public class myClass {
[...]
private ObjA a;
private ObjB b;
[...]
public void myClass() {
[...]
this.a = new ObjectFactory().createObjA();
this.b = new ObjectFactory().createObjB();
[...]
}
public void init() {
this.initA();
this.initB();
}
private void initA() {
this.a.setCounter(BigInteger.ZERO);
this.a.setData = "";
}
private void initB() {
this.b.setCounter(BigInteger.ZERO);
this.b.setData = "";
}
[...]
}
initA和initB相同,无法访问库代码,无法创建通用接口,如何避免重复代码?我的意思是,有可能有这样的东西吗?
private void initObj([ObjA|ObjB] obj) {
obj.setCounter(BigInteger.ZERO);
obj.setData = "";
}
谢谢!非常感谢!
附录
请注意,我无权访问底层库,因此我无法以任何方式添加修改 类、接口、wsdl 或 xsd。 同样在我看来,我是否使用 ws、jaxb 或其他库并不重要:您可以想象没有注释的 ObjA 和 ObjB,如下所示:
public static class ObjA {
protected BigInteger counter;
protected String data;
[...]
}
public static class ObjB {
protected BigInteger counter;
protected String data;
[...]
}
而问题的症结并没有改变
因为它们没有通用接口(或父接口 class?),我想要走的路是 java 反射。
像"init(Class clazz)"一样自己创建一些反射辅助方法并调用构造函数。
请记住,java 反射在大多数情况下都是不好的做法,因此请确保没有 other/better 方法可以实现您的目标。
我想您正在使用 JAXB。您可以阅读对象列表。 看到这个 post:JAXB Unmarshalling: List of objects
我假设 类 是使用某种工具为您生成的,可能是 maven cxf-codegen-plugin 等。 如果是这种情况,您需要修改 WSDL 和 XSD,以便生成令您满意的 DTO 类。 如果 WSDL 已提供给您,那么您只需按原样接受服务即可?
知道公用方法都是同名的,还可以用反射吗?
所以你会用原始反射做这样的事情:
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void initObject(Object o) throws Exception {
if (!(o instanceof ObjA)&&!(o instanceof ObjB)) return;
Method m = o.getClass().getMethod("setCounter",java.math.BigInteger.class);
m.invoke(o,BigInteger.ZERO);
m = o.getClass().getMethod("setData",java.lang.String.class);
m.invoke(o,"");
}
public static void main(final String[] args) throws Exception {
List<Object>objects = new ArrayList<Object>();
//this is like your factory method
Object o = Class.forName("ObjA").newInstance();
initObject(o);
objects.add(o);
o = Class.forName("ObjB").newInstance();
initObject(o);
objects.add(o);
}
}
如果您想使用一个库,您可以使用 JXPath 和 see docs here 但我认为就您的目的而言,原始反射可能没问题。不需要非常复杂的反射库。