咱们常常看到一些 Java 性能优化的书或者理念,说不要在循环内定义变量,这样会占用过多的内存影响性能,而要在循环外面定义。接触 Java 这么久以来,相信不少 Java 程序员都被这种代码性能优化策略所误导。java
看下面两个示例,示例1在循环外定义变量,示例2是在循环内定义变量。程序员
/** * 循环外定义变量 */ private static void outer() { Javastack javastack = null; for (int i = 0; i < 10; i++) { javastack = new Javastack(); } } /** * 循环内定义变量 */ private static void inner() { for (int i = 0; i < 10; i++) { Javastack javastack = new Javastack(); } }
先来分析这两个示例吧。性能优化
循环外定义变量,变量循环内每次引用指向不一样的对象实例,每次循环变动对象实例时,上一次被指向的对象就会被销毁,直到最后一个循环。这样,循环结束后,这个变量还存在,并指向循环内最后一个对象实例,其余对象都销毁了。微信
这样,本应该是循环体内的生命周期变量被扩散到了循环外,若是循环外依旧用这个变量,会致使后面的业务发生不可预知的后果。这种问题在笔者工做当中常常会遇到,看下面的例子。性能
/** * 循环外定义变量 */ private static void outer() { Javastack javastack1 = null; for (int i = 0; i < 10; i++) { javastack1 = new Javastack(); } Javastack javastack2 = userDao.getUser(10); }
上面定义了一个 javastack2
,若是此时在后续代码或者传递到别的方法时写错了,用了 javastack1
,那这时不就有问题了吗?这只是一方面,还有若是用同一变量名,当这一变量被重用时发生异常,原本发生异常应该是 null 值的,结果获得了是以前循环体内的值。优化
循环内定义变量,和循环外略有不一样的是,每次都会建立新的局部变量指向新的对象实例,每一个变量和对象的生命周期仅限于在循环体以内,并且每次循环结束该局部变量和对象实例都会随着循环体的结束而销毁,因此不存在占用更多的内存这一说法。spa
两种用法都会建立相同数量的对象实例,只不过循环内会反复建立相同数量的局部变量,栈内存垃圾回收频率也会更高,但对于堆垃圾回收带来的性能影响和变量生命周期带来的业务影响来讲,栈内存这点性能影响能够忽略不计。code
因此,建议使用循环内定义变量,这种把变量的生命周期限制在循环体范围内,也不会出现业务上重用变量而致使严重的问题。对象
推荐:Spring Boot & Cloud 最强技术教程教程
扫描关注咱们的微信公众号,干货天天更新。