90 % Java 程序员被误导的一个性能优化策略

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 值的,结果得到了是之前循环体内的值。

循环内定义变量

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

总结

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

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

原文发布于微信公众号 - Java技术栈(javastack)

原文发表时间:2018-07-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

Golang语言--细节汇总

slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用...自动 计算长度,而声明slice时,方括号内没有任何字符。 对于slice有几个...

3689
来自专栏老司机的技术博客

人人都能学会的python编程教程9:dict和set

dict和我们小时候用的字典很像,如果你想查一个汉字,你只需要根据某一个拼音就可以很快速的查询到它。

6238
来自专栏Pythonista

封装与扩展性

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码...

923
来自专栏C/C++基础

C++ struct与union

编码运行环境:VS2012+Win32+Debug Win32既表示运行平台是Windows 32bits操作系统,又表示生成32bits的应用程序。

781
来自专栏思考的代码世界

Python编程从入门到实践之遍历列表|第2天

通常情况下,我们需要对列表的所有元素进行操作,这个时候就需要遍历整个列表。循环采用for。

4257
来自专栏编程

宝宝都能学会的python编程教程4:关系运算符与循环

关系运算符 if 语句 实际应用中的程序,大多不是一撮而就的,而是根据条件不同存在很多分支。 最基本的条件分支结构是if...else...语句即如果。。。否则...

2129
来自专栏老司机的技术博客

宝宝都能学会的python编程教程9:dict和set

dict字典 dict和我们小时候用的字典很像,如果你想查一个汉字,你只需要根据某一个拼音就可以很快速的查询到它。 ? 在字典的索引表里(比如部首表)查这个字...

3535
来自专栏求索之路

Effective Java笔记(不含反序列化、并发、注解和枚举)

最近把Effective Java复习了一遍,其中有比较多的java最佳实践可以在平时编程中用到。反序列化、并发、注解和枚举这四章没看,并发这本书里讲的比较简...

35711
来自专栏互联网杂技

理解javascript闭包前,先理解作用域链

1. 全局作用域(Global Scope)   在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:   (1)最外层函数和...

3605
来自专栏aCloudDeveloper

指向函数的指针

Author: bakari   Date: 2012.8.8 做好总结我觉得是把知识学扎实必不可少的实践环节。这个知识点是当初自己在学习这一块做的一些笔记,现...

1956

扫码关注云+社区

领取腾讯云代金券