2015-02-11 66 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