一、简介

代码优化,目的有两个,第一个就是为了让我们的代码体积尽可能变小,看起来比较清晰,第二个就是为了提高代码运行效率。个人觉得,在平时编写代码的同时,尽量要求自己,养成良好的编码习惯,一个小的优化点,积攒起来肯定会有好处,也能对我们自己以后的代码风格有好处。本文参考了阿里巴巴开发者手册以及网上一些博客,个人进行编码实践之后,重新总结了一些平时项目中常用的一些代码优化技巧,供大家参考学习。

二、优化方法详解

【1】变量的声明尽量不要以下划线或美元符号开始,也不要以下划线或美元符号结束

//不推荐用法String _name = "weixiaohuai";String $name = "weixiaohuai";String name_ = "weixiaohuai";String name$ = "weixiaohuai";//推荐用法(见名知意)String name = "weixiaohuai";

【2】变量的声明尽量不要使用拼音,也不要使用中文,应该使用英文

//不推荐用法String xingming = "weixiaohuai";String 姓名 = "weixiaohuai";//推荐用法String stuName = "weixiaohuai";

【3】 类名、方法名、参数名称都必须采用驼峰命名规则(见名知意)

        //不推荐用法String studentname = "weixiaohuai";
//        void printstudentname(String studentname) {}//推荐用法String studentName = "weixiaohuai";
//        void printStudentName(String studentName) {}

【4】常量必须全部使用大写字母,并且多个英文之间用下划线_隔开

        //不推荐用法final int max_num = 1024;final String accessKey = "test";//推荐用法final int MAX_NUM = 1024;final String ACCESS_KEY = "test";

【5】声明数组的时候尽量采用String[]方式

       //不推荐用法String arr[] = {"a", "b", "c"};//推荐用法String[] newArr = {"a", "b", "c"};

【6】声明变量、属性的时候尽量使用通俗易懂的英文,必须随意取名字

        //不推荐用法int a = 10;//推荐用法int num = 10;

【7】接口中的方法、属性尽量不要加任何访问修饰符

public interface UserRepository {//不推荐用法
//    public abstract void getUserDetail(Long userId);
//    public static final String COMPAN_EMAIL = "12345678@qq.com";//推荐用法void getUserDetail(Long userId);String COMPAN_EMAIL = "12345678@qq.com";}

【8】枚举类命名尽量加上Enum后缀,Enum成员名称必须使用大写字母,字母间使用下划线_分隔开

public enum OrderStatusEnum {ORDER_NOT_START("ORDER_NOT_START"),ORDER_END("ORDER_END"),ORDER_DOING("ORDER_DOING");private String value;OrderStatusEnum(String value) {this.value = value;}public String getValue() {return value;}public static OrderStatusEnum getName(String value) {switch (value) {case "ORDER_NOT_START":return ORDER_NOT_START;case "ORDER_DOING":return ORDER_DOING;case "ORDER_END":return ORDER_END;default:return null;}}}

【9】各层命名规约:

* A) Service/DAO层方法命名规约

* 1) 获取单个对象的方法用get做前缀。 如: getUser()

* 2) 获取多个对象的方法用list做前缀。 如: getUserList()

* 3) 获取统计值的方法用count做前缀。 如:countUser()

* 4) 插入的方法用save/insert做前缀。 如:saveUser()

* 5) 删除的方法用remove/delete做前缀。 如:deleteUser()

* 6) 修改的方法用update做前缀。 如:updateUser()

* B) 领域模型命名规约

* 1) 数据对象:xxxDO,xxx即为数据表名。 如:UserDO

* 2) 数据传输对象:xxxDTO,xxx为业务领域相关的名称。 如:UserDTO

* 3) 展示对象:xxxVO,xxx一般为网页名称。 如: userVO

* 4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO.

【10】尽量不要允许任何魔法值(即未经定义的常量)直接出现在代码中

        //不推荐用法String userId = "123456";String key = "KEY" + userId;

【11】long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

        //不推荐用法Long chineseScore = 100l;long mathScore = 90l;//推荐用法Long englishScore = 100L;long networkScore = 90L;

【12】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可

 public class Person {private String personName;private int age;public static final String name = "weixiaohuai";public static void printName() {}public static void printNames(int id, String... names) {for (String name : names) {System.out.println(name);}}@Overridepublic String toString() {return "Person{" +"personName='" + personName + '\'' +", age=" + age +'}';}public void sayHello() {}}
        //不推荐用法Person person = new Person();person.printName();System.out.println(person.name);//推荐用法Person.printName();System.out.println(Person.name);

【13】相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。 说明:可变参数必须放置在参数列表的最后。

   public static void printNames(int id, String... names) {for (String name : names) {System.out.println(name);}}     //推荐用法Person.printNames(1, "zhangsan", "lisi", "wangwu");

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

        //不推荐用法String personName = null;System.out.println(personName.equals("zhangsan"));//推荐用法System.out.println("zhangsan".equals(personName));System.out.println(Objects.equals("zhangsan", personName));

【15】序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。 说明:注意serialVersionUID不一致会抛出序列化运行时异常。

【16】POJO类必须写toString方法。如果继承了另一个POJO类,注意在前面加一下super.toString。

* 说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。

@Overridepublic String toString() {return "Person{" +"personName='" + personName + '\'' +", age=" + age +'}';}

【17】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。

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

        // 不推荐用法String str = "start";for (int i = 0; i < 100; i++) {str = str + "hello";}//推荐用法StringBuilder stringBuilder = new StringBuilder("start");for (int i = 0; i < 100; i++) {stringBuilder.append("hello");}

【18】类成员以及方法尽量严格控制访问权限

* 1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。

* 2) 工具类不允许有public或default构造方法。

* 3) 类非static成员变量并且与子类共享,必须是protected。

* 4) 类非static成员变量并且仅在本类使用,必须是private。

* 5) 类static成员变量如果仅在本类使用,必须是private。

* 6) 若是static成员变量,必须考虑是否为final。

* 7) 类成员方法只供类内部调用,必须是private。

* 8) 类成员方法只对继承类公开,那么限制为protected。

【19】使用集合转数组的方法,使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()。

List<String> namesList = new ArrayList<>(10);namesList.add("zhangsan");namesList.add("lisi");String[] namesArr = new String[namesList.size()];//不推荐用法
//        Object[] array = namesList.toArray();//推荐用法namesArr = namesList.toArray(namesArr);System.out.println(Arrays.toString(namesArr));

【20】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。

        //不推荐用法List<String> list = new ArrayList<>(10);list.add("1");list.add("2");for (String item : list) {if ("1".equals(item)) {list.remove(item);}}//推荐用法Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String item = iterator.next();if ("1".equals(item)) {iterator.remove();}}

【21】尽量使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历

* 说明: :keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高

       //不推荐用法Set<String> keySet = map.keySet();for (String k : keySet) {Object value = map.get(k);System.out.println(k + ", " + value);}//推荐用法Map<String, Object> map = new HashMap<>(10);map.put("name", "weixiaohuai");map.put("sex", "male");map.put("age", "20");Set<Map.Entry<String, Object>> entrySet = map.entrySet();for (Map.Entry<String, Object> entry : entrySet) {String entryKey = entry.getKey();Object entryValue = entry.getValue();System.out.println(entryKey + ", " + entryValue);}

【22】在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有

        //推荐用法String switchKey = "a";switch (switchKey) {case "a":break;case "b":case "c":break;default:break;}

【23】获取当前毫秒数尽量使用System.currentTimeMillis(); 而不是new Date().getTime()

        //不推荐用法long currentTimeMillis = System.currentTimeMillis();//推荐用法long time = new Date().getTime();

【24】在使用可能抛出运行时异常的代码时,尽量使用预先检查机制来规避运行时异常,不应该使用try-catch来处理这些运行时异常

        //不推荐用法Person p = null;try {p.sayHello();} catch (NullPointerException e) {e.printStackTrace();}//推荐用法if (null != p) {p.sayHello();}

【25】不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句

 //不推荐用法public String say() {try {//...return "a";} catch (Exception e) {e.printStackTrace();} finally {return "b";}}

【26】尽量重用对象,避免不必要的new创建对象

       /*** 优化方法1: 尽量重用对象,避免不必要的new创建对象*/String namePrefix = "wei";String nameSuffix = "xiaohuai";//不推荐用法//Java虚拟机会重新创建一个新的对象返回,影响效率String name = namePrefix + nameSuffix;System.out.println(name);//推荐用法//字符串拼接使用StringBuilder或者StringBufferStringBuilder stringBuilder = new StringBuilder("wei");stringBuilder.append("xiaohuai");System.out.println(stringBuilder);

【27】在进行IO操作的时候,要及时关闭流对象

        //推荐用法InputStream inputStream = null;try {inputStream = new FileInputStream(new File("D:/a.txt"));} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (null != inputStream) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}

【28】for循环遍历的时候尽量减少对变量(集合长度)的重复计算

        //不推荐用法List<String> list = new ArrayList<>(10);list.add("zhangsan");list.add("lisi");for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}//推荐用法//先计算集合的总长度,避免重复计算,在集合非常大的时候效率会提高很多for (int i = 0, size = list.size(); i < size; i++) {System.out.println(list.get(i));}

【29】在需要用到的时候才创建变量(懒加载)

        //不推荐使用String str = "wangwu";int idx = 1;if (idx == 1) {System.out.println(str);}//推荐使用(在需要使用的时候才创建)if (idx == 1) {String s = "wangwu";System.out.println(s);}

【30】复制大量数据时,使用System.arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

//推荐用法String[] names = new String[]{"a", "b", "c", "d"};String[] newNames = new String[names.length];System.arraycopy(names, 0, newNames, 0, names.length);//[a, b, c, d]System.out.println(Arrays.toString(newNames));

【31】在循环中不要不断创建对象引用

        //不推荐用法//这样在内存中会存在10000份person对象的引用,耗内存资源for (int i = 0; i < 10000; i++) {Person person = new Person();//...一系列操作}//推荐用法//内存中只有一份Person对象引用,每次new Person()创建对象,person对象引用指向不同的Person,节省内存资源Person person = null;for (int i = 0; i < 10000; i++) {person = new Person();//...一系列操作}

【32】避免随意使用静态变量

        //不推荐用法//Java的垃圾回收器不会回收static对象,如果A类不被卸载,那么引用B指向的B对象会常驻内存,直到程序终止public class A {private static B b = new B();}

【33】常量尽量定义为static final,这样在编译的时候就可以把值放入常量池中,避免计算常量的值

static final String ACCESS_TOKEN = "abcd";

【34】随机访问比较多、顺序插入的场景使用ArrayList,中间插入、删除、更新多、随机访问少的场景使用LinkedList

* 说明: ArrayList底层实现是数组,随机访问直接通过下标获取,速度快,但是删除、中间插入需要移动元素,速度慢 * LinkedList底层实现是链表,插入删除只需要改变指针,速度快,但是随机访问需要循环遍历,速度慢

【35】字符串变量和字符串常量equals的时候将字符串常量写在前面

        //不推荐用法//可能会发生NotPointerException空指针异常String word = "abc";if (word.equals("abc")) {//...}//推荐用法if ("abc".equals(word)) {//...}//或boolean isEqual = Objects.equals("abc", word);

【36】基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+""最慢

       //推荐使用int i = 10;String iStr = Integer.toString(i);String s = String.valueOf(10);//不推荐String s1 = i + "";

【37】使用效率高的方法遍历Map,尽量使用entrySet,直接将key/value都查询出来。

//推荐使用
Map<String, Object> map = new HashMap<>(10);map.put("name", "weixiaohuai");map.put("age", "20");Set<Map.Entry<String, Object>> entries = map.entrySet();for (Map.Entry<String, Object> entry : entries) {String key = entry.getKey();Object value = entry.getValue();}

【38】底层使用可变数组的数据结构尽量指定长度

        //推荐用法List<String> newList = new ArrayList<>(10);Map<String, Object> newMap = new HashMap<>(10);

【39】String类尽量使用StringBuffer、StringBuilder

        //不推荐用法//java 虚拟机会在堆中创建三个变量,"wei" 、"xiaohuai"、 "weixiaohuai,最终newName指向"weixiaohuai","wei"、"xiaohuai"就没有对象引用它们,需要GC回收,耗性能String newNamePrefix = "wei";String newName = newNamePrefix + "xiaohuai";//推荐用法//java虚拟机只会在堆中开辟一个空间"wei",执行append时只会在 "wei" 的空间上 + "xiaohuai" , 避免了GC的回收,也避免了内存的浪费StringBuilder sb = new StringBuilder("wei");sb.append("xiaohuai");

【40】尽可能多使用三目运算符,代码看起来会比较清晰

* 说明: 对于if-else结构的,视情况优化为三目运算符

        //不推荐用法int a = 10;if (a > 10) {System.out.println("a大于10");} else {System.out.println("a小于10");}//推荐用法System.out.println(a > 10 ? "a大于10" : "a小于10");

三、总结

以上就是一些Java代码优化的方法,仅供大家参考学习,欢迎大家补充一起学习,实际项目中,注意养成良好的编码习惯,让代码看起来更清晰易懂。

Java代码优化的一些方法(总结)相关推荐

  1. java一般方法有哪些方法有哪些方法_Java代码优化有哪些方法?

    Java代码优化是Java编程开发很重要的一个步骤,Java代码优化要注重细节优化,一个两个的细节的优化,产生的效果不大,但是如果处处都能注意代码优化,对代码减少体积.提高代码运行效率是有巨大帮助的, ...

  2. java中的Native方法

    由于Native方法最近经常碰到,好奇之下便找到了这篇博客,内容还是相当好理解的,下面即是正文部分: 一. 什么是Native Method 简单地讲,一个Native Method就是一个java调 ...

  3. Java代码优化方案 J2ME内存优化

    从几本书上,N个网站上整理的一些JAVA代码优化方案,最近的项目只有1M内存可用,必须很抠门了~J2ME项目更要注意的 避免内存溢出 l 不用的对象释放(置空) 如 : a不为空时 a=new obj ...

  4. 提高效率的Java代码优化小技巧

    可以提高效率的Java代码优化小技巧 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面 ...

  5. 开发者应该掌握的Java代码优化技能

    就像鲸鱼吃虾米一样,也许吃一个两个虾米对于鲸鱼来说作用不大,但是吃的虾米多了,鲸鱼自然饱了. 代码优化一样,也许一个两个的优化,对于提升代码的运行效率意义不大,但是只要处处都能注意代码优化,总体来说对 ...

  6. JVM 虚拟机原理、Java 代码优化、秒杀系统

    JVM虚拟机原理 JVM组成架构 Java是一种跨平台的语言,JVM屏蔽了底层系统的不同,为Java字节码文件构造了一个统一的运行环境. Java 字节码文件 Java 如何实现在不同操作系统.不同硬 ...

  7. 使用 Jtest:一款优秀的 Java 代码优化和测试工具

     Jtest 简介 Jtest 是 Parasoft 公司推出的一款针对 Java 语言的自动化代码优化和测试工具,它通过自动化实现对 Java 应用程序的单元测试和编码规范校验,从而提高代码的可 ...

  8. java带参数的方法笔记_具有Java参数的方法的类声明

    类声明可以包含在Java中具有参数的方法.演示此过程的程序如下: 示例class Message { public void messagePrint(String msg) { System.out ...

  9. java.util.Collections.synchronizedSet()方法的使用

    下面的例子显示java.util.Collections.synchronizedSet()方法的使用 package com.;import java.util.*;public class Col ...

  10. java -version cmd_java如何运行步骤cmd?Java执行cmd命令方法有哪些?

    写好一个java程序之后,我们的最终目的就是可以正确的运行程序,如果程序运行正确了,那么代码也就没有什么问题了,可是java如何运行步骤cmd?接下来,我们就来给大家讲解一下这方面的内容. 1.首先用 ...

最新文章

  1. 入职五年回顾(八) 2013年3月
  2. 开挂的 00 后!17 岁「天才少女」被 8 所世界名校录取,最终选择 MIT 计算机系...
  3. 如何编写数据库存储过程?
  4. VC++6中的一些快捷键(陆续补充中。。。)
  5. neroLinux3.x的序列号
  6. Ascll字符串转换到二进制字符串
  7. 基于JAVA+SpringMVC+Mybatis+MYSQL的公寓租赁系统
  8. 清明节,如何用代码让网页变灰
  9. linux c++ 输出到终端,如何将彩色文本输出到Linux终端?
  10. 视觉SLAM十四讲_4-相机模型和非线性优化
  11. GridView中设置DataFormatString无效的解决方法.
  12. 微信小程序调用域名服务器的服务
  13. Win:在 Windows Server 中的 NIC Teaming
  14. Oracle11g64位安装教程
  15. 论文笔记:Improving Conversational Recommender Systems via Knowledge Graph based Semantic Fusion(KDD2020)
  16. UVALive - 4987 Evacuation Plan
  17. 计算机网络基础学习笔记
  18. 程序员:迟到1分钟罚300,加班却视而不见,月底工资让人寒心
  19. 《Web全栈工程师的自我修养》浓缩笔记(上)
  20. 内存读数据和磁盘读数据的区别

热门文章

  1. 容器技术Docker K8s 28 容器服务ACK基础与进阶-弹性伸缩
  2. 易筋SpringBoot 2.1 | 第十三篇:SpringBoot综合应用多个DataSoure
  3. android开发第一个程序,Android开发入门之第一个android程序
  4. ppocr 源码阅读:ppocr.modeling.architecures 之build_model模块
  5. 深度神经网络的正则化
  6. 简述deque容器的插入删除原理
  7. jar命令成功完成 java -jar 命令却提示“没有主清单属性”!
  8. android studio for android learning (二十八) android基础知识
  9. 不变子空间与线性变换的矩阵之间的关系
  10. oracle数据库第十一章答案,[转载]《互联网数据库》网上作业练习题10-11章答案...