java代码的优化

随着自己做开发时间的增长,越来越理解雷布斯说的: 敲代码要像写诗一样美。也能理解有一次面试官问我你对代码有洁癖吗?

一段好的代码会让人看就像诗一样,也像一个干净房间会让人看去很舒服。

一段好的项目代码我觉得可以用这三个维度去分析。1)性能 2)可扩展性3)可读性

有关代码的规范早在很久就有阿里巴巴的java开发手册,里面有非常多的规范。太多了,自己也没完全记住,抽空也会时不时再去翻翻。

接下来就写一些有关性能和可读性一些习惯,不全以后想到什么会再补充进来。

一、性能考虑

1、必须注意: 不对数据库层做任何操作 如果业务的确需要,那也最好注解说明原因

2、尽量减少对变量的重复计算

在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

for (int i = 0; i < list.size(); i++)
{...}
//建议修改成:
for (int i = 0, length = list.size(); i < length; i++)
{...}

这样list.size()只会调用一次,减少性能消耗。

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

这个习惯需要培养,在写逻辑的时候,尤其是创建对象的时候是否需要考虑懒加载。

例如:

A a = new A();
if (i == 1)
{
list.add(a);
}
//建议替换为:
if (i == 1)
{
A a = new A();
list.add(a);
}

4、字符串累加

1)循环外: 字符串拼接可以直接使用String的+操作,没有必要通过StringBuilder进行append.

2)循环内: 好的做法是在循环外声明StringBuilder对象,在循环内进行手动append。不论循环多少层都只有一个 StringBuilder对象。

反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");
//不在循环体内其实可以直接用加号,优化后一行代码:
String sb="a"+"b"+"c"+"d";

有关JDK不同版本对String拼接的优化可以参考:jdk不同版本对String拼接的优化分析

5、尽量避免使用split

split由于支持正则表达式,所以效率比较低。

替代

  String str1="a,b,c,d,,f,g";
//可以考虑使用apache的StringUtils.split(string,char)
List<String> list = Arrays.asList(StringUtils.split(str1, ","));
//可以考虑guava工具
List<String> list1=Splitter.on(",").splitToList(str1);

6、确定Stringbuffer的容量

Stringbuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建Stringbuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

例子:

 Stringbuffer buffer = new Stringbuffer(); // violation
buffer.append ("hello");
//更正好:为stringbuffer提供寝大小。一般循环体内使用都可以知道大小
Stringbuffer buffer = new Stringbuffer(max);
buffer.append ("hello");

7、使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法

它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。

String[] str = new String[] { "a", "b" };
List list = Arrays.asList(str);
//第一种情况:list.add("c"); 运行时异常。
//第二种情况:str[0]= "gujin"; 那么list.get(0)也会随之修改。

8、查找数组元素,可以用Arrays.asList(T[] array).contains(T obj)

二、可读性考虑

1、推荐尽量少用 else, if-else 的方式

可以考虑:

 if(condition){
...
return obj; }
// 接着写 else 的业务逻辑代码;

说明:如果非得使用if()...else if()...else...方式表达逻辑,【强制】请勿超过3层,超过请使用策略设计模式。

正例:逻辑上超过 3 层的 if-else 代码可以使用卫语句,或者状态模式来实现。

接下来抽空会写一篇超过三层if-else更好的解决方案博客。

2、在 if/else/for/while/do 语句中必须使用大括号,即使只有一行代码

避免使用: if (condition) statements;

3、使用条件操作符替代"if (cond) return; else return;" 结构

//条件操作符更加的简捷
if (isdone) {
return 0;
} else {
return 10;
}
//更正
return (isdone ? 0 : 10);

4、Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals

正例: "test".equals(object);

反例: object.equals("test");

说明:推荐使用java.util.Objects (JDK7引入的工具类)

5、不允许出现任何魔法值(即未经定义的常量)直接出现在代码中

反例

String key="Id#taobao_"+tradeId;cache.put(key, value);

6、取反操作符(!)降低程序的可读性,所以不要总是使用

 boolean method (boolean a, boolean b) {
if (!a)
return !a;
else
return !b;
}

7、注释掉的代码尽量要配合说明,而不是简单的注释掉

代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没 有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。

8、特殊注释标记,请注明标记人与标记时间

  1. 待办事宜(TODO)

    java代码之美(11)---java代码的优化的更多相关文章

    1. Java 9 揭秘(11. Java Shell)

      Tips 做一个终身学习的人. 在本章节中,主要介绍以下内容: 什么是Java shell JShell工具和JShell API是什么 如何配置JShell工具 如何使用JShell工具对Java代 ...

    2. java代码之美(15)---Java8 Function、Consumer、Supplier

      Java8 Function.Consumer.Supplier 有关JDK8新特性之前写了三篇博客: 1.java代码之美(1)---Java8 Lambda 2.java代码之美(2)---Jav ...

    3. java代码之美(14)---Java8 函数式接口

      Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加 ...

    4. java代码之美(16) ---Java8 Optional

      Java8 Optional 一句话介绍Optional类:使用JDK8的Optional类来防止NullPointerException(空指针异常)问题. 一.前言 在我们开放过程中,碰到的异常中 ...

    5. 更新整理本人所有博文中提供的代码与工具(Java,2013.11)

      为了更方便地管理博文中涉及的各种代码与工具资源,现在把这些资源迁移到 Google Code 中,有兴趣者可前往下载. Java 1.<高效 Java Web 应用开发框架 JessMA v3. ...

    6. java代码之美(10)---Java8 Map中的computeIfAbsent方法

      Map中的computeIfAbsent方法 Map接口的实现类如HashMap,ConcurrentHashMap,HashTable等继承了此方法,通过此方法可以在特定需求下,让你的代码更加简洁. ...

    7. java代码之美(2)---Java8 Stream

      Stream 第一次看到Stream表达式就深深把我吸引,用它可以使你的代码更加整洁而且对集合的操作效率也会大大提高,如果你还没有用到java8的Stream特性,那就说明你确实out啦. 一.概述 ...

    8. java代码之美(1)---Lambda

      Lambda 一.概述 1.什么是Lambda表达式 Lambda 表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符.返回值声明和名字. 它可以写出更简洁.更灵活的代码.作为一种 ...

    9. 1.JAVA中使用JNI调用C++代码学习笔记

      Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI?  Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 ( ...

    随机推荐

    1. Java虚拟机-类加载

      虚拟机把描述类的数据从Class文件加载到内存,并对数据进行检验.转换解析和初始化,最终形成了可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制.在Java语言里,类型的加载.连接和初始化过 ...

    2. 为什么Python编程被国家教育如此重视?请开始你的表演!

      高考新宠 在高考更改之前,提起编程,人们可能更多的会想起c语言之类的. 然而,高考更始之后,Python这门编程说话一夜之间传进了千家万户. 现实上,在IEEE(美国电气电子工程师学会出书的旗舰杂志) ...

    3. Tomcat PermGen space的解决方案

      Tomcat报告 Caused by: java.lang.OutOfMemoryError: PermGen space异常 内存溢出PermGen space的全称是Permanent Gener ...

    4. zabbix 3.4 ubuntu 16 用腾讯企业邮箱作为告警邮箱

      最近一直在研究zabbix监控系统,今天调试了腾讯企业邮箱作为告警邮箱的设置,本次方式是用内置email组件. 第一步: 选择Administration-->Media Types--> ...

    5. python_选择结构

      >>> if 3>2:print('ok') ok>>> if True:print(3);print(5) >>> chTesst=['1 ...

    6. 前端工程化(三)---Vue的开发模式

      从0开始,构建前后端分离应用 导航 前端工程化(一)---工程基础目录搭建 前端工程化(二)---webpack配置 前端工程化(三)---Vue的开发模式 前端工程化(四)---helloWord ...

    7. linux常用的时间获取函数(time,gettimeofday,clock_gettime,_ftime,localtime,strftime )

      time()提供了秒级的精确度 1.头文件 <time.h> 2.函数原型 time_t time(time_t * timer) 函数返回从TC1970-1-1 0:0:0开始到现在的秒 ...

    8. SSM-Spring-08:Spring的静态代理初窥案例

      ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 静态代理 java的设计模式的代理模式,就是静态代理 写在前面的话,静态代理的优点和缺点 优点:可以在不改变一 ...

    9. SVG的动态之美-搜狗地铁图重构散记

      搜狗地图发布了新版的移动端地铁图,改版初衷是为了用户交互体验的提升以及性能的改善.原版地铁图被用户吐槽最多的是pinch缩放不流畅.无过渡动画.拖拽边界不合理等等,大体上都是交互体验上的问题.实际上原 ...

    10. 软件配置管理及SVN的使用

      一.配置管理   1. 管理整个软件生命周期中的配置项    配置项:软件生命周期中产出的各种输出成果,如需求文档.设计文档.代码.测试相关文档   2.管理配置项的变化(核心)   3.使用配置管理 ...