APP下载

浅谈Java代码性能优化

2018-12-20陈俟伶重庆工程学院

数码世界 2018年12期
关键词:常量调用代码

陈俟伶 重庆工程学院

1. 代码优化细节

1.1 不要导入一些不使用的类,不要创建一些不使用的对象

这毫无意义,如果代码中出现”The value of the local variable i is not used”、”The import java.util is never used”,那么请删除这些无用的内容。

1.2 尽量指定方法、类的final修饰符

带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是final的。为类指定final修饰符可以让类不可以被继承,为方法指定final修饰符可以让方法不可以被重写。如果指定了一个类为final,则该类所有的方法都是final的。Java编译器会寻找机会内联所有的final方法,内联对于提升Java运行效率作用重大,具体参见Java运行期优化。这样可以使性能平均提高50%。

1.3 尽量使用局部变量

调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变量,如静态变量、实例变量等,都在堆中创建,速度较慢。另外,栈中创建的变量,随着方法的运行结束,这些内容就没了,不需要额外的垃圾回收。

1.4 将常量声明为static final,并以大写命名

这样在编译期间就可以把这些内容放入常量池中,避免运行期间计算生成常量的值。另外,将常量的名字以大写命名也可以方便区分出常量与变量

1.5 尽量减少对变量的重复计算

明确一个概念,对方法的调用,即使方法中只有一句语句,也是有消耗的,包括创建栈帧、调用方法时保护现场、调用方法完毕时恢复现场等。所以例如下面的操作:

for (int i = 0; i < list.size();i++ )

建 议 替 换 为:for (int i = 0, int length = list.size(); i

这样,在list.size()很大的时候,就减少了很多的消耗

1.6 尽量采用懒加载的策略,即在需要的时候才创建

例如:String str = "aaa";if (i == 1) { list.add(str); }

建议替换为:if (i == 1) { String str = "aaa"; list.add(str); }

1.7 循环内不要不断创建对象引用

例 如:for (int i = 1; i < count;i++){Object obj =new Object();}

这种做法会导致内存中有count份Object对象引用存在,count很大的话,就耗费内存了,建议为改为:Object obj = null;for (int i = 1; i

这样的话,内存中只有一份Object对象引用,每次new Object()的时候,Object对象引用指向不同的Object罢了,但是内存中只有一份,这样就大大节省了内存空间了。

1.8 使用同步代码块替代同步方法

除非能确定一整个方法都是需要进行同步的,否则尽量使用同步代码块,避免对那些不需要进行同步的代码也进行了同步,影响了代码执行效率。

1.9 不要让public方法中有太多的形参

方法太多形参的话主要有两点坏处:一是违反了面向对象的编程思想,Java讲求一切都是对象,太多的形参,和面向对象的编程思想并不契合。二是参数太多势必导致方法调用的出错概率增加。

1.10 把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+””最慢。

1.11 尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销。

1.12 如果能估计到待添加的内容长度,为底层以数组方式实现的集合、工具类指定初始长度

比 如 ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等。

1.13 顺序插入和随机访问比较多的场景使用ArrayList,元素删除和中间插入比较多的场景使用LinkedList

1.14 使用最有效率的方式去遍历Map

遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value,那么推荐使用的、效率最高的方式是: HashMap map =new HashMap(); map.put("001", " 张三 ");

Set set = map.entrySet(); Iterator it = set.iterator(); while(it.hasNext()) { Map.Entry entry = it.next(); System.out.println(entry.getKey() + " " + entry.getValue()); } 如果你只是想遍历一下这个Map的key值,那用”Set set = map.keySet();”会比较合适一些。

1.15 不要在循环中使用try…catch…,应该把其放在最外层

1.16 使用带缓冲的输入输出流进行IO操作

带 缓 冲 的 输 入 输 出 流,即 BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,这可以极大地提升IO效率

1.17 及时关闭流

Java编程过程中,进行数据库连接、I/O流操作时务必小心,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销,稍有不慎,将会导致严重的后果。

1.18 对资源的close()建议分开操作

例如:try{ XXX.close(); YYY.close(); }catch (Exception e) {...}

建议修改为:try{ XXX.close(); }catch (Exception e) {... }try{YYY.close(); }catch (Exception e) {... }虽然有些麻烦,却能避免资源泄露。优化前,如果XXX.close()抛异常了,那么就进入了cath块中了,YYY.close()不会执行,YYY这块资源就不会回收了,一直占用着,这样的代码一多,是可能引起资源句柄泄露的。而优化后,就保证了无论如何XXX和YYY都会被close掉。

2. 结束语

代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃的小虾米一多之后,鲸鱼就被喂饱了。代码优化也是一样,如果项目着眼于尽快无BUG上线,那么此时可以抓大放小,代码的细节可以不精打细磨;但是如果有足够的时间开发、维护代码,这时候就必须考虑每个可以优化的细节了,一个一个细小的优化点累积起来,对于代码的运行效率绝对是有提升的。

猜你喜欢

常量调用代码
科学照亮世界
——卡文迪什测定万有引力常量
一次函数的学习引导
系统虚拟化环境下客户机系统调用信息捕获与分析①
VHDL中常用的数据对象
神秘的代码
一周机构净增(减)仓股前20名
一行代码玩完19亿元卫星
近期连续上涨7天以上的股
基于属性数据的系统调用过滤方法
利用RFC技术实现SAP系统接口通信