我们经常看到一些 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 值的,结果得到了是之前循环体内的值。

循环内定义变量

循环内定义变量,和循环外略有不同的是,每次都会创建新的局部变量指向新的对象实例,每个变量和对象的生命周期仅限于在循环体之内,而且每次循环结束该局部变量和对象实例都会随着循环体的结束而销毁,所以不存在占用更多的内存这一说法。

总结

两种用法都会创建相同数量的对象实例,只不过循环内会反复创建相同数量的局部变量,栈内存垃圾回收频率也会更高,但对于堆垃圾回收带来的性能影响和变量生命周期带来的业务影响来说,栈内存这点性能影响可以忽略不计。

所以,建议使用循环内定义变量,这种把变量的生命周期限制在循环体范围内,也不会出现业务上重用变量而导致严重的问题。

推荐:Spring Boot & Cloud 最强技术教程

90 % Java 程序员被误导的一个性能优化策略的更多相关文章

  1. Spring AOP注解为什么失效?90%Java程序员不知道

    使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方加,不然不会生效. 如下面几种场景 1.Controller直接调用Se ...

  2. 正式工作的前奏——一个Java程序员的实习总结(1)

    不知不觉,到深圳实习已经三个礼拜了.跟在暑假的三个半月实习不一样,这次收获更多,感受更好,算是摆脱了那次实习给我带来的阴影(这个会放到以后才说). 在知乎上,有这么一个问题,你现在最想跟刚工作时的你说 ...

  3. 一个3年Java程序员的坎与选择

    前言 LZ 15年本科毕业,不知不觉3年过去了,去年底裸辞回到成都来发展,年后开始找工作,面试了几家公司,现在整理整理做个总结,也方便规划下一个3到5年以及和广大想要进阶的Java程序员同胞们共勉. ...

  4. 做为一个Java程序员,你需要哪些傍身的技能?

    最近总有些断断续续的思考,想想从我入行以来,我到底学会了什么,做成过什么,以后要做什么,如何提升自己······· 工作3年了,常听人说3年,5年,10年是程序员的坎,每过一个都会有新的想法,新的改变 ...

  5. 如何成为一个优秀的java程序员

    Java程序员有许多应遵循的守则或最佳实践方式.本文概述了每个开发者最应该遵循的10条守则或戒律,如果不遵循它们,将会导致灾难性后果. 1. 为代码添加注释(Add comments to your ...

  6. 一个10年Java程序员的年终总结,献给还在迷茫中的你

    我越来越担心我作为一个Java程序员的未来. 恍然间,发现自己在这个行业里已经摸爬滚打将近10年了,原以为自己就凭已有的项目经验和工作经历怎么着也应该算得上是一个业内比较资历的人士了,但是今年在换工作 ...

  7. 0~5年一个Java程序员的晋升之路

    在程序界流行着一种默认的说法叫“黄金5年”,也就是一个程序员从入职的时候算起,前五年的选择直接影响着整个职业生涯中的职业发展方向和薪资走向,如何走好这5年,彻底从一个刚入行的菜鸟蜕变成可以以不变应万变 ...

  8. 对于长沙互联网发展,一个外来两年Java程序员的所见所感所愿

    惟楚有材,于斯为盛 本文有感于2019长沙互联网求职招聘大会,内容比较多,但都是我自己的一些所见.所感和所愿. 2019年3月的最后一天,参加2019长沙互联网求职招聘大会,看到了很多的招聘企业,也看 ...

  9. (转)java程序员进入名企需要掌握哪些,立一个flag

    想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,在面试之前到底需要准备哪些东西呢?面试时面试官想了解你的什么专业技能,以下都是一个合格Java软件工程师所要具备的. 一.专业技能 熟练的 ...

随机推荐

  1. asp.net文件/大文件上传需要配置的项目整理

    HTTP 错误 404.13 - Not Found 请求筛选模块被配置为拒绝超过请求内容长度的请求. 最可能的原因: •Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值. 可尝 ...

  2. MFC笔记2

    1.Create()函数创建,该函数原型如下: BOOL Create( LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* ...

  3. 云笔记项目-补充JS面向对象编程基础知识

    简单介绍: 此部分知识为在做云笔记项目中补充,因为云笔记项目中涉及到前端js,里面写了很多js脚本,用到了创建js属性和方法,在js中直接声明的属性和方法最终都会变成window的对象,即其成为了全局 ...

  4. JAVA远程调试

    1.远程端启动必须添加jvm参数 -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=${debug_port} 其中de ...

  5. python--第十三天总结(html ,css 语法)

    概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏览器 ...

  6. python中获取python版本号的方法

    import platform print platform.python_version()

  7. CF 317 A. Lengthening Sticks(容斥+组合数学)

    传送门:点我 A. Lengthening Sticks  time limit per test        1 second You are given three sticks with po ...

  8. Python自动化测试用例设计--自动化测试用例与手工测试用例区别与联系

    1. 前言 手工测试用例是针对手工测试人员,自动化测试用例是针对自动化测试框架,前者是手工测试用例人员应用手工方式进行用例解析,后者是应用脚本技术进行用例解析,两者最大的各自特点在于,前者具有较好的异 ...

  9. django mysql 数据库配置

    在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库. DATABASES = { 'default': { 'ENGINE': 'django.db. ...

  10. 106. Construct Binary Tree from Inorder and Postorder Traversal根据后中序数组恢复出原来的树

    [抄题]: Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assum ...