2011-08-24 47 views
2

我有一個用Java編寫的應用程序。我有3個類mysql_query,tablesetup,table_action。現在在每個類的類中,我創建了其他類的對象,這會導致遞歸對象調用。我可以用什麼方法來解決這個問題?Java中的StackOverflow異常

例如:

在mysql_query.java我有

 
public class mysql_query{ 
    tablesetup tablesetup = new tablesetup(); 
    table_action table_action = new table_action(); 
} 

在tablesetup.java我有

 
public class tablesetup{ 
    mysql_query mysql_query= new mysql_query(); 
    table_action table_action = new table_action(); 
} 

類似地,在table_action.java我有

 
public class table_action{ 
    mysql_query mysql_query= new mysql_query(); 
    tablesetup tablesetup= new tablesetup(); 
} 

- EDIT-- 傳遞一個類對象到其他構造函數不會在我的情況下鍛鍊,因爲我有很多像這樣的依賴類。那麼通常程序員如何安排這些類?我可以使用interface嗎?在這種情況下使用是否合適?

+0

似乎所有3類實例,另2作爲屬性。這是你的意圖嗎? –

回答

7
  • tablesetup你實例在table_action一個table_action
  • 你實例化一個tablesetup

我猜你看到的循環 - 第一個創建第二的新實例,這將創建一個新的實例第一個,創建第​​二個的新實例,依此類推,直到你的堆棧(持有方法和構造函數調用)被填充。

稍微澄清一點 - 當你通過構造函數實例化一個對象時,它的所有字段都被初始化。因此,當您實例化table_action時,將調用new tablesetup()以初始化tablesetuptablesetup變量。

循環依賴不是一件好事,但你可以擁有它們。創建table_action時,您只需傳遞對現有tablesetup的引用即可。

除此之外 - 你沒有使用正確的java命名。你不應該使用小寫類和下劃線。專有名稱是TableSetup,TableActionMySQLQuery。除大寫外,變量名也一樣。他們應該由mysqlQuerytableSetup

+0

只是nitpick,我更喜歡MySqlQuery :) –

+0

對於那個,我最喜歡的例子是'HttpURLConnection'。去圖.. – Bozho

+0

@Bozho:我瞭解tat概念..謝謝你。我想知道這個問題的解決方案。檢查我的編輯! – Deepak

2

這種問題的一種解決方案稱爲延遲初始化。正確地初始化對象可能是一項非常複雜的任務。一般來說,你應該避免在構造函數中初始化太多的其他對象(或者隱式構造函數,就像你的情況一樣)。這裏有一個例子:

public class table_action{ 
    // Never access members directly: 
    private mysql_query mysql_query; 
    private tablesetup tablesetup; 

    // Only access getters 
    mysql_query get_mysql_query() { 
    if (mysql_query == null) { 
     mysql_query = new mysql_query(); 
    } 
    return mysql_query; 
    } 

    tablesetup get_tablesetup() { 
    if (tablesetup == null) { 
     tablesetup = new tablesetup(); 
    } 
    return tablesetup; 
    } 
} 

我不能告訴你,如果上面是要正常工作,但它會給你懶初始化的想法。

UPDATE:在您編輯之後,我的回答將不足以滿足您的使用案例。您可能想要在專用工廠的外部管理對象的生命週期。請參閱此處工廠模式的基本說明:http://en.wikipedia.org/wiki/Factory_method_pattern

處理模型對象的複雜生命週期的另一種方法是使用框架,如EMF:http://www.eclipse.org/modeling/emf/。 EMF幫助您在Java中正確建模1:1,1:nm:n關係,正確處理/維護雙向引用。我不知道這是否會矯枉過正你,雖然......

+0

這是* one *的解決方案。請注意,它要求對象是可變的,這在某些情況下並不理想。另外,這意味着'tablesetup'不會引用創建它的同一個table_action,除非將它傳遞給構造函數(這會返回類似的問題)。 –

+0

也許不是。但「不變的初始化」似乎太複雜,無法解釋手頭的問題。關於「幾個參考」,OP的問題已經是這種情況。我猜想,手頭的物品並不真正擁有自己的狀態。 –

+0

@Lukas Eder:我必須在同一個文件的許多地方使用類對象。我認爲在這種情況下,懶惰初始化並不合適。檢查我的編輯..你怎麼看? – Deepak

2

您只能創建一個實例,然後把它傳遞給別人這樣的:

public class mysql_query{ 
    tablesetup tablesetup; 
    table_action table_action; 
    public void mysql_query() { 
    tablesetup tablesetup = new tablesetup(this); 
    table_action table_action = new table_action(this); 
    } 
} 

public class tablesetup{ 
    mysql_query mysql_query; 
    table_action table_action; 
    public void tablesetup(mysql_query query) { 
    mysql_query = query; 
    table_action = new table_action(this); 
    } 
} 

public class table_action{ 
    mysql_query mysql_query; 
    tablesetup tablesetup; 
    public void table_action(mysql_query query, tablesetup setup) { 
     mysql_query = query; 
     tablesetup = setup; 
    } 
} 
+0

感謝。檢查我的編輯並告訴我你的想法! – Deepak

3

Bozho已經顯示出失敗的原因,但對於解決方案,有多種選擇:

  • 打破循環引用;爲什麼每個班級都需要參考另一個班級?
  • 使一類的「大師」,並使其構造通this到構造爲其他類:

    class Foo 
    { 
        private final Bar bar; 
    
        public Foo() 
        { 
         bar = new Bar(this); 
        } 
    } 
    
    class Bar 
    { 
        private final Foo foo; 
    
        public Bar(Foo foo) 
        { 
         this.foo = foo; 
        } 
    } 
    

    這樣做的缺點是:

    • 的依賴仍然相當緊張
    • 你讓this逃離Foo的構造函數;通常一個物體在完成構建之前不應該公佈它的存在。
  • 使類可變的,並且具有創建所有這些沒有他們的依賴單獨的方法,然後設置依賴事後

+0

@Joh Skeet:謝謝你的回覆。我在編輯中解釋了我的問題。你對那個怎麼想的 ? – Deepak