由Java中toString()方法引发的无意识的递归想到的
先看一段很简单的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>>
由Java中toString()方法引发的无意识的递归想到的的更多相关文章
- 自己(转)JAVA中toString方法的作用
JAVA中toString方法的作用 因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.print ...
- JAVA中toString方法的作用
因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不 ...
- JAVA中toString方法的作用(转)
因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不 ...
- JAVA中toString方法
因为它是Object里面已经有了的方法,而所有类都是继承Object,所以"所有对象都有这个方法". 它通常只是为了方便输出,比如System.out.println(xx),括号 ...
- Java中的方法应用
一.如何定义java中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 语法: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 public.protected.priv ...
- Java中的方法(形参及实参)return返回类型
如何定义 Java 中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 一般情况下,定义一个方法的语法是: 其中: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 pub ...
- java中的方法method
java中的方法必须存在于类class里,不能独立存在.类是描述具有某种特征的事物,方法则是这类 事物具有的某种功能,通过调用方法可以实现某种特定的功能.方法名一般以小写的动词开头. 例: publi ...
- Java09-java语法基础(八)java中的方法
Java09-java语法基础(八)java中的方法 一.方法(函数/过程):是一个程序块,可以完成某种功能 1.java中方法的定义格式 [访问控制修饰符] 返回值类型 方法名(参数列表){ 方 ...
- Java学习笔记十一:Java中的方法
Java中的方法 一:什么是方法: 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 学过C语言或者其他语言的应该都知道函数这个东西,在Java中,其实方法就是函数,只不过叫法不同,在 ...
随机推荐
- wpf 自定义窗口,最大化时不覆盖任务栏
相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 WindowState="Maximized& ...
- hibernate进行多表联合查询
hibernate是按照hql语句来进行查询的, 里面所使用的表名, 其实是实体类的名字, hql语句的写法并没有多大差别, 是在返回结果的时候要稍微做一些处理 //使用hibernate进行多表查询 ...
- 自己随意写了个简单的依赖jquery的轮播图
//轮播图 function Switcher(obj){ this.box = $(obj.box); this.width = this.box.width(); this.banner = $( ...
- 未能加载文件或程序集“ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=n
这个可能是因为,缺少文件ICSharpCode.SharpZipLib.dll文件. 我从网上下载了个dll文件,放到根目录中自己好了.
- [PHP]Yaf + composer 引起大幅性能下降
composer.json 文件可以用命令 composer init 创建,命令是交互式的. 也可以直接编辑一个 json 文件,如下: repositories 中 url 使用中国全量镜像地址. ...
- PHP创建缩略图造成图片质量低下的完美解决方法
近期弄个论坛,在首页要有个排名,显示评论最多的前十位用户的列表,列表有个略图是用户最新上传的作品,如果使用原来的图,图片过大,首页加载过慢,因此要使用略图 以上来使用imagecopyresized这 ...
- [转贴]有关Angular 2.0的一切
对Angular 2.0的策略有疑问吗?就在这里提吧.在接下来的这篇文章里,我会解释Angular 2.0的主要特性区域,以及每个变化背后的动机.每个部分之后,我将提供自己在设计过程中的意见和见解,包 ...
- 【转】jquery validate验证框架与kindeditor使用需二次提交的问题
原文:http://blog.csdn.net/wlsyn/article/details/11536399在使用jquery的验证框架对kindeditor富文本编辑器进行验证的过程中,发现提 交时 ...
- 斯坦福第三课:线性代数回顾(Linear Algebra Review)
3.1 矩阵和向量 3.2 加法和标量乘法 3.3 矩阵向量乘法 3.4 矩阵乘法 3.5 矩阵乘法的性质 3.6 逆.转置 3.1 矩阵和向量 如图:这个是 4×2 矩阵,即 4 行 ...
- MySQL数据库小实验
实验1 1.创建数据表 CREATE TABLE guest( Accounts ) NOT NULL, Details ) NOT NULL, Date ) NOT NULL, ,), Class ...