由Java中toString()办法激发的无意识的递归想到的

    添加时间:2013-7-20 点击量:

    先看一段很简单的java代码:



    toString()/
    
    @author jeffwong
    /

    public class InfiniteRecursion {
    public String toString(){
    return InfiniteRecursion address + this + \n;
    }

    public static void main(String[] args) {
    InfiniteRecursion obj = new InfiniteRecursion();
    System.out.println(obj);
    }
    }



    运行后,我们看到了一串异常信息,StackOverflow了:



    爆栈的原因凡是是因为递归或者无穷轮回,上方的代码造成客栈溢出的直接原因是递归,下面来解析一下造成递归的原因:


    定义类InfiniteRecursion,底本经由过程toString办法打印出当前对象的内存地址,获取当前对象当然会想到this关键字。在toString办法内,Java编译器发明一个字符串后面跟着一个加号,加号后面的对象不是String类型,所以编译器试着主动将this转换为字符串类型,也就是调用this.toString()办法,偏偏this所指代的这个对象从头实现了toString办法,于是造成轮回络续地调用toString办法,如许就产生了递归调用。


    上方这种toString()被Bruce Eckel总结称为无意识的递归,在.NET傍边同样实用(重写ToString办法),类似代码我就不贴了。


    这种无意识的递归说到底还是应用类持续不当造成的。也许你会说其实这底子没有什么技巧难度的,类持续用对了不就行了吗,不就是持续自Object的戋戋一个ToString办法吗?


    若是你手上保护的代码是一个基类代码雄厚,持续链很深,含有多量包装类,类调用关系错杂……用对就行了,说起来不免难免太轻易。再说一个由类持续激发的血案的真实案例:


    用户反馈我司某首要营业项目组的线上体系某页面无常打开,直观结果就是页面一向loading迟迟打不开。开辟人员费了很大力量据说还动用了Windbg神器和传说中的架构师才排查到是一个页面办法调用的题目,为了申明题目我们临时定名该页面为A,页面A持续自自定义基类页面B,然后呈现题目的原因大致解析如下:


    1、A页面某办法func1触发调用了基类B的另一个办法func2;


    2、B中的办法func2履行的时辰,发明被A重写了,所以就去履行A重写的办法func2;


    3、A重写的func2内部又调用了func1,如许就从头触发A的func1的履行。


    如许,一个神不知鬼不觉惊寰宇泣鬼神的无意识递归就形成了。


    饱满而真实的类持续的副感化的经典案例介绍到此停止。

    明天,你还会用类持续吗,你还敢用类持续吗,你还忍心用类持续吗?



    参考:<<Thinking in Java>>

    原来,再大的房子,再大的床,没有相爱的人陪伴,都只是冰冷的物质。而如果身边有爱人陪伴,即使房子小,床小,也觉得无关紧要,因为这些物质上面有了爱的温度,成了家的元素。—— 何珞《婚房》#书摘#
    分享到: