1. 程式人生 > >JAVA中迴圈依賴的相關問題

JAVA中迴圈依賴的相關問題

作為一個剛畢業的渣渣,下面說一下自己對java中迴圈問題的理解,有不正確的歡迎各位大佬留言。

1.類A的構造方法中建立類B,類B的構造方法中建立A,物件是如何被建立的?

public class A {
    B b = new B();
    A(){
        System.out.println("A的構造方法");
    }
}
public class B {
    A a = new A();
    B(){
        System.out.println("B的構造方法");
    }
}
public class TestCase {
    public static void main(String[] args) {
        A a = new A();
    }
}

結果:棧溢位,很明顯,AB互相new對方死迴圈。


2.物件A持有物件B的引用,物件B持有物件A的引用,此外AB再無被引用的地方,那麼A,B會被GC回收嗎?

答案肯定是會回收,那麼gc通過什麼方式來回收呢?

gc處理物件有一種策略是使用引用計數的方法,每個物件被持有引用就+1,gc會掃描所有物件的引用,如果發現引用為0的就直接回收到,然而我們這種情況兩個物件互相引用,其引用數不等於0,所以引用計數策略不能解決這個問題;在GC策略中還有另一種策略通過可達性演算法,來判斷物件是否存活,演算法的基本思想是通過一系列被稱為gc roots的物件最為起始點,從這些節點開始往下搜尋,搜尋所走過的路徑稱為引用鏈,當一個物件沒有任何引用鏈可達時證明此物件不可用。

3.Spring框架中向beanA中注入B,向Bean B中注入A,Spring是如何解決迴圈依賴的?

之前去面試,面試官問到這個問題,一直自己使用spring,spring用起來也很爽,然而spring如何建立物件,如何幫我們注入物件,如何處理存在迴圈依賴的問題,當時想了一種思路,就是在建立一個物件的時候建立一個標記池,沒依賴一個就將其新增到標記池,比如說A中注入B,先將B加入標記池,再來建立B,在建立B的時候發現有需要建立A然後將A加入標記池,同理當我們再將B再次加入標記池時會發現其已存在,因此判定為迴圈引用,至此不建立第二個B。這個方法實現起來比較簡單,然而就是容易出現空指標;第二個思路是使用懶載入的方式,所有待注入的物件都是在直接呼叫的時候建立,比如說A中注入B在建立A的時候並不是直接建立A物件而是返回A的代理物件,在代理A的過程中我們不建立B物件,而是將getB()方法前面新增this.b = new B();通過這樣,達到只有當我們使用物件時才去建立它,因此就不存在迴圈問題了。