java对象循环依赖问题

原文地址:http://leihuang.net/2014/11/13/Cycular-Dependency/

假设我们有一个类A,它包含了一个B的对象,同时类B也包含了一个A对象。那么此时不管你实例化哪一个类,都会出现StackOverflowError错误,这就是java对象循环依赖问题。类似于鸡和蛋的问题。

首先我们看下面这段错误的代码,分析其错误的地方。

public class CyclicDependencies {
    public static void main(String args[]){
        Chicken c = new Chicken() ;
        //Egg e = new Egg() ;
    }
}

class Chicken{
    private Egg e ;
    private int age ;
    public Chicken(){
        e = new Egg() ;
        setAge(10) ;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}
class Egg{
    private Chicken chicken ;
    private int weight ;
    public Egg(){
        chicken = new Chicken() ;
        setWeight(1) ;
    }
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }
}
Exception in thread "main" java.lang.StackOverflowError

这是上面代码报的错误,因为当你创建一个Chicken对象时,同时也需要一个Egg对象,而一个Egg对象也需要一个Chicken对象,这样一直循环下去就发生了栈溢出的错误。

那么如何来解决这个问题呢?我们可以给Chicken写一个代理类ChickenProxy,这样Egg包含的不再是Chicken而是代理类ChickenProxy,这样就利用了第三方来解决循环依赖问题。代码如下。

public class CyclicDependencies {
    public static void main(String args[]){
        Chicken c = new Chicken() ;
        Egg e = new Egg(c) ;

        System.out.println(c.getAge());
        System.out.println(e.getWeight());
    }
}

interface ChickenProxy{
    int getAge();
    void setAge(int age) ;
}

class Chicken implements ChickenProxy{
    private Egg e ;
    private int age ;
    public Chicken(){
        e = new Egg(this) ;
        setAge(10) ;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}
class Egg{
    private ChickenProxy chicken ;
    private int weight ;
    public Egg(Chicken c){
        chicken = c ;
        setWeight(1) ;
    }
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }
}


2014-11-13 15:41:41

Brave,Happy,Thanksgiving !

时间: 2024-10-10 09:34:08

java对象循环依赖问题的相关文章

JAVA循环依赖

最近看到一个问题:如果有两个类A和B,A类中有一个B的对象b,B类中有一个A的对象a,那么如何解决这两个类的相互依赖关系呢? 示例代码1 public class Test{ public static void main(String[] args) { B testb = new B(); } } class A{ public B b; public A (){ b = new B(); } public void printB(){ System.out.println("Ab"

剑指架构师系列-Struts2构造函数的循环依赖注入

Struts2可以完成构造函数的循环依赖注入,来看看Struts2的大师们是怎么做到的吧! 首先定义IBlood与BloodImpl类: public interface IBlood { } public class BloodImpl implements IBlood{ private IPeople people; @Inject public BloodImpl(@Inject IPeople people) { System.out.println("Blood 构造函数被调用.&q

java中的进程与线程及java对象的内存结构【转】

原文地址:http://rainforc.iteye.com/blog/2039501 1.实现线程的三种方式: 使用内核线程实现 内核线程(Kernel Thread, KLT)就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上.程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口——轻量级进程(Light Weight Process,LWP),轻量级进程就是我们通常意义上所讲的线程,由于每个轻量

Java虚拟机(三)垃圾标记算法与Java对象的生命周期

相关文章 Java虚拟机系列 前言 这一节我们来简单的介绍垃圾收集器,并学习垃圾标记的算法:引用计数算法和根搜索算法,为了更好的理解根搜索算法,会在文章的最后介绍Java对象在虚拟机中的生命周期. 1.垃圾收集器概述 垃圾收集器(Garbage Collection),通常被称作GC.提到GC,很多人认为它是伴随Java而出现的,其实GC出现的时间要比Java早太多了,它是1960诞生于MIT的Lisp. GC主要做了两个工作,一个是内存的划分和分配,一个是对垃圾进行回收.关于内存的划分和分配,

json转java对象

用了平台之后很少再接触到java和js的底层代码,前几天远程帮一个萌新远程调试代码,这个萌新按照网上的教程去将json字符转java对象却一直报错.真相是它的json字符串格式不对,他的明明是一个数组,却写成一个对象,虽然用json在线校验是没错的,但是代表的含义是不一样的~~~(此处捂脸~偷笑~哈哈)所以在了解怎么转换之前一定要熟悉json的格式,我之所以写博客就是希望自己不要把以前的东西遗忘了,不希望自己的有多正规,只当这是个日记,偶尔自己看看也能和别人多多交流一下. 那么json和java

Spring中-IOC-Bean的初始化-循环依赖的解决

前言 在实际工作中,经常由于设计不佳或者各种因素,导致类之间相互依赖.这些类可能单独使用时不会出问题,但是在使用Spring进行管理的时候可能就会抛出BeanCurrentlyInCreationException等异常 .当抛出这种异常时表示Spring解决不了该循环依赖,本文将简要说明Spring对于循环依赖的解决方法. 循环依赖的产生和解决的前提 循环依赖的产生可能有很多种情况,例如: A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象 A的构造方法中依赖了B的实例对象

Spring循环依赖

Spring-bean的循环依赖以及解决方式 Spring里面Bean的生命周期和循环依赖问题 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的相互依赖关系.循环调用其实就是一个死循环,除非有终结条件. Spring中循环依赖场景有: (1)构造器的循环依赖 (2)field属性的循环依赖 其中,构造器的循环依赖问题无法解决,只能拋出BeanCurre

002-多线程-锁-同步锁-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现

一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. synchronized结论: 1.java5.0之前,协调线程间对共享对象的访问的机制只有synchronized和volatile,但是内置锁在功能上存在一些局限性,jdk5增加了Lock以及ReentrantLock. 2.java5.0,增加了一种新的机制:显式锁ReentrantLock,注意它

测试一下25道Spring经典面试题你会几道?循环依赖面试详解

前言 先看看什么是循环依赖当一个ClassA依赖于ClassB,然后ClassB又反过来依赖ClassA,这就形成了一个循环依赖:ClassA -> ClassB -> ClassA循环依赖-->2个或以上bean 互相持有对方,最终形成闭环.Spring中循环依赖的场景:1.构造器的循环依赖.(spring也无能为力)2.setter循环依赖:field属性的循环依赖[setter方式 单例,默认方式-->通过递归方法找出当前Bean所依赖的Bean,然后提前缓存[会放入Cach