2015-02-11 152 views
2

我有一个调用各种web服务使用外部库的proyect。这个库给我反对这样的:Java:相同的对象,如何避免重复的代码

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 = ""; 
    } 

谢谢! Muchas Gracias!

请注意我有底层库中没有访问,所以我可以不加修改类,接口,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; 
    [...] 
} 

和问题的症结没有按”改变。

+0

如果你不能创建一个通用的接口(在本例中是抽象类),你必须编写代码来初始化'ObjA'类型和'ObjB'类型,而不管你做什么。 – EpicPandaForce 2015-02-11 16:44:14

+0

您可以使用动态方法(反射或BeanUtil)使用相同方法处理不同类型的数据。然而,这有很多自己的问题(静态分析不知道它),所以我通常会远离它。我们对上下文不了解,所以也可能有其他解决方案。不要忘记与API提供商交谈。 – eckes 2015-02-11 20:35:55

+0

我只想做一个超类,手工编辑生成的(猜测它只是每个类的一个地方),然后做一个阅读我和一个什么和为什么做视频。 – tgkprog 2015-02-12 07:35:34

回答

1

我假定类为你使用某种工具的产生,也许是行家CXF-CODEGEN,插件等 如果是这种情况,您需要修改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 但我认为你的目的的原始反射可能是罚款。不需要大量复杂的反射库。

+0

我无法修改WSDL或XSD。我正在考虑反思,但正如@ L.Butz所述,这是一个不好的做法。 – 2015-02-11 17:45:15

+0

这通常是不好的做法,因为很难做到正确。但是反射实际上用在你选择的每个主要的Java库中,特别是Jackson等。我想不出有什么方法可以解决你的问题,它不涉及某种基于反射的解决方案。 你可以尝试像xpath一样做你的refelction http://commons.apache.org/proper/commons-jxpath/ – Richard 2015-02-11 17:49:17

+0

我认为你是对的。你会用一个解决ObjA和ObjB问题的例子来发布答案,这样我最终可以接受它吗? – 2015-02-11 18:08:24

0

由于他们没有一个通用的接口(或父类?),我想要走的路是用java反射。

自己创建一些反射帮助器方法,比如“init(Class clazz)”,并调用这些构造器。

请记住,在大多数情况下,Java反射是不好的做法,所以请确保没有其他/更好的方法来实现您的目标。

+0

技术上可行,但当我试图想象“助手方法”和产生的代码的签名时,我微微颤抖。编译时错误检查将延迟到运行时。 – laune 2015-02-11 17:01:12

1

我想你正在使用JAXB。您可以阅读对象列表。 看到这个帖子:JAXB Unmarshalling: List of objects

+0

这是如何避免OP的myClass中的代码重复?请解释! – laune 2015-02-11 16:52:10

+0

这不是对象的名单,他们是两个相同的对象,但有两个名字定义,它就像是我lillte书我的好电影:bookdata和filmdata是相同的但不同的对象 – 2015-02-11 17:07:12

+0

为了提供更好的帮助,您应该提供更多信息来解决问题,例如:您是否使用JAXB?你会打电话给1 web服务,并与该答复,你会建立对象A和B?或者他们会从不同的ws获得信息? – PSA 2015-02-11 17:22:48