2017-05-05 59 views
0

我此刻創造一個大項目爲我公司,有很多數據結構和shizle的。我期待爲我下面的問題一個很好的解決方案:替代構造器返回null

由於Java有沒有可能有一個構造函數返回NULL(至少我的研究說)我需要一個很好的替代它。

比方說,我有以下代碼(只是一個例子,實際的項目是比較複雜的。):

public abstract class SuperClass 
{ 
    public SuperClass(Element element) 
    { 
     if(element != null) 
      readElement(element); 
    } 

    public abstract void readElement(Element element); 
} 

public class Foo extends SuperClass 
{ 
    private Bar bar1; 
    private Bar bar2; 
    private Bar bar3; 
    //... 

    public Foo(Element element) 
    { 
     super(element); 
    } 

    @Override 
    public void readElement(Element element) 
    { 
     this.bar1 = new Bar(element.getChild("bar1")); 
     this.bar2 = new Bar(element.getChild("bar2")); 
     this.bar3 = new Bar(element.getChild("bar3")); 
     //... 
    } 
} 

public class Bar extends SuperClass 
{ 
    private String value; 

    public Bar(Element element) 
    { 
     super(element); 
    } 

    @Override 
    public void readElement(Element element) 
    { 
     this.value = element.getChildText("value"); 
    } 
} 

的Element.getChild(字符串名稱)函數是從jdom2(XML解析器),使用通過XML文件閱讀。如果沒有找到給定名字的孩子,它可以並且將返回null。 我在這個例子的基礎上編寫了我的項目,愚蠢地想,如果named函數返回null,變量(例如bar1)將爲null。但是,由於命名函數包含一個「新Bar(...)」,它不會爲空,而是一個空對象。 但我想要「空」變量爲空,所以我可以在迭代項目中的所有數據結構時輕鬆地跳過這些變量。 我會保存在「getChild(...)」函數返回的對象到一個局部變量「lElement」再有這樣的事:

if(lElement != null) 
    bar1 = lElement; 

但我有超過50個不同的數據結構像那些在我的例子並且在它們中有足夠多的變量,它們由「readElement(...)」函數初始化。這個想法需要太多的編輯,甚至可能會有相當的性能。這對我來說似乎有點......「醜陋」。至少對於這個數量的變量。所以我需要一些東西,它對性能沒有任何影響,並且很容易,因爲讓構造函數返回null。我不想在這些函數中更改太多的代碼。 我也有這樣的想法:如果「元素元素」等於null,讓數據結構設置爲null,但經過快速研究後,這個想法立即被刪除^^。刪除自己的對象將不起作用,並且不合邏輯。

所以basicly我能解決這個問題我自己。但可能它不會是最有效的方式。無論是編輯代碼還是編碼性能。 因此,我問你們,你們將如何解決這個問題。反思不僅僅是我的例子中的兩個簡單的數據結構,而是50個類+使用這個系統。

我希望你能幫助我,我的任何不良英語道歉。我來自德國^^。 我已經在Java中現在編碼超過5年(「專業」去年以來),所以這是一個有點尷尬的對我來說,已經沒有想過這個問題早。但現在回到完全不同的東西已經太遲了。

預先感謝您!

+0

不是返回'null',而是應該拋出一個(運行時)異常。返回'null'迫使你用*'null'檢查*來混淆你的代碼,這更加醜陋。 –

+0

也許在構造函數中調用抽象方法是一個不幸的選擇。另見[this](http://stackoverflow.com/questions/15327417/is-it-ok-to-call-abstract-method-from-constructor-in-java)SO問題。 –

+0

@Timothy使用異常會迫使我用try/catches來混亂我的代碼,在我看來這更糟糕。當第一個獲得空指針時,我不想讓所有變量都跳過。 – Apahdos

回答

0

構造函數定義任意對象的初始化。因此他們永遠不會返回值。

我認爲缺少hasElement方法是一個主要的設計缺陷,但是如果你堅持返回null,你可以。

在任何情況下,您都應該使用泛型和方法引用(> = Java 8)。

你可以在你的給定需求的代碼示例中使用wrap方法(使用繼承來允許子類更容易讀取子節點)。

public void readElement(Element element) { 
    this.bar1 = wrap(element.getChild("bar1"), Bar::new); 
    this.bar2 = wrap(element.getChild("bar1"), Bar::new); 
    this.bar3 = wrap(element.getChild("bar1"), Bar::new); 
} 

protected <T> T wrap(Element element, Function<Element, T> elem) { 
    if (element == null) { 
     return null; // Not a good value 
    } 
    return elem.apply(element); 
} 
+0

嗯。到目前爲止,我從未使用過這種包裝方法。 Function <>類正在做什麼?我不會在每次使用wrap(...)時都通過傳遞一個新的本地類Function <..>?來寫一個新的Function。因爲函數<...>似乎是一個接口。我還沒有添加這樣的事情,因爲我認爲它可能會花費太多的性能和編程工作量,每次初始化時都會有空檢查... – Apahdos

+0

...一個變量。正如我所說,擁有超過50多個不同的數據結構,每個數據結構都有多達10個不同的變量(其中一些是列表),使用「if(hasElement(...){...}」會變得非常困難 – Apahdos

+0

由於它的功能,我命名了方法包裝因爲它包含了任何其他類型(T)中的給定元素,因爲您可以傳遞類的構造函數(Bar: :new)。hasElement應該在jdom中實現,所以你可以用element.hasChild(「foo」)?new Baz(element.getChild(「foo」)):null來簡化賦值。 – manf

0

返回構造函數null的替代方法是返回null的工廠方法。

雖然你不能寫

class SomeClass { 
    public SomeClass(Node node) { 
     if (node.isEmpty()) return null; // Does not compile 
     ... 
    } 
} 

你當然可以這樣寫:

class SomeClass { 
    private SomeClass(Node node) { 
     // Self-check: this should never happen 
     if (node.isEmpty()) { 
      throw new IllegalArgumentException("node"); 
     } 
     ... 
    } 
    public static SomeClass makeFromNode(Node node) { 
     if (node.isEmpty()) { 
      return null; 
     } 
     return new SomeClass(node); 
    } 
} 

更換構造函數調用makeFromNode電話將讓您處理的情況下,當節點在一個簡單而統一的null辦法。

+1

啊,這實際上是一個很好的做法。改變我所有的電話將是一項非常努力的工作,但它實際上並沒有改變任何有關性能的內容,而且似乎需要(至少我認爲是這樣)以最少的努力來改變電話,因爲我有一個頂級的電話我可以添加靜態功能。非常感謝你!再次學到新的東西^^ – Apahdos

+0

啊......等等。這可能不那麼容易。我有很多不同的數據結構,這被稱爲。他們都有不同的吸氣。所以我需要手動爲每一個類創建方法,因爲(在我的原始帖子的例子中)超類沒有函數,但Bar會有一個getValue()方法,例如...我在這裏錯過了什麼,或者我不能將你的方法寫入超類,所以我不需要手動爲每個類製作它。 – Apahdos

+0

@Apahdos靜態方法不可重寫,因此基類中的方法最終會從基類調用構造函數,這不是您想要的。如果您不想瀏覽所有類並進行此修改,則可以爲您希望創建的每個子類創建一個單獨的具有靜態方法的「MyClassFactory」類。但是,您確實需要每個類的一個方法。 – dasblinkenlight