JAVA中循环依赖的相关问题

来源:互联网 发布:vx什么软件 编辑:程序博客网 时间:2024/06/01 16:25

作为一个刚毕业的渣渣,下面说一下自己对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();通过这样,达到只有当我们使用对象时才去创建它,因此就不存在循环问题了。









原创粉丝点击