Java代码优化的一些方法(总结)
一、简介
代码优化,目的有两个,第一个就是为了让我们的代码体积尽可能变小,看起来比较清晰,第二个就是为了提高代码运行效率。个人觉得,在平时编写代码的同时,尽量要求自己,养成良好的编码习惯,一个小的优化点,积攒起来肯定会有好处,也能对我们自己以后的代码风格有好处。本文参考了阿里巴巴开发者手册以及网上一些博客,个人进行编码实践之后,重新总结了一些平时项目中常用的一些代码优化技巧,供大家参考学习。
二、优化方法详解
【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代码优化的一些方法(总结)相关推荐
- java一般方法有哪些方法有哪些方法_Java代码优化有哪些方法?
Java代码优化是Java编程开发很重要的一个步骤,Java代码优化要注重细节优化,一个两个的细节的优化,产生的效果不大,但是如果处处都能注意代码优化,对代码减少体积.提高代码运行效率是有巨大帮助的, ...
- java中的Native方法
由于Native方法最近经常碰到,好奇之下便找到了这篇博客,内容还是相当好理解的,下面即是正文部分: 一. 什么是Native Method 简单地讲,一个Native Method就是一个java调 ...
- Java代码优化方案 J2ME内存优化
从几本书上,N个网站上整理的一些JAVA代码优化方案,最近的项目只有1M内存可用,必须很抠门了~J2ME项目更要注意的 避免内存溢出 l 不用的对象释放(置空) 如 : a不为空时 a=new obj ...
- 提高效率的Java代码优化小技巧
可以提高效率的Java代码优化小技巧 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面 ...
- 开发者应该掌握的Java代码优化技能
就像鲸鱼吃虾米一样,也许吃一个两个虾米对于鲸鱼来说作用不大,但是吃的虾米多了,鲸鱼自然饱了. 代码优化一样,也许一个两个的优化,对于提升代码的运行效率意义不大,但是只要处处都能注意代码优化,总体来说对 ...
- JVM 虚拟机原理、Java 代码优化、秒杀系统
JVM虚拟机原理 JVM组成架构 Java是一种跨平台的语言,JVM屏蔽了底层系统的不同,为Java字节码文件构造了一个统一的运行环境. Java 字节码文件 Java 如何实现在不同操作系统.不同硬 ...
- 使用 Jtest:一款优秀的 Java 代码优化和测试工具
Jtest 简介 Jtest 是 Parasoft 公司推出的一款针对 Java 语言的自动化代码优化和测试工具,它通过自动化实现对 Java 应用程序的单元测试和编码规范校验,从而提高代码的可 ...
- java带参数的方法笔记_具有Java参数的方法的类声明
类声明可以包含在Java中具有参数的方法.演示此过程的程序如下: 示例class Message { public void messagePrint(String msg) { System.out ...
- java.util.Collections.synchronizedSet()方法的使用
下面的例子显示java.util.Collections.synchronizedSet()方法的使用 package com.;import java.util.*;public class Col ...
- java -version cmd_java如何运行步骤cmd?Java执行cmd命令方法有哪些?
写好一个java程序之后,我们的最终目的就是可以正确的运行程序,如果程序运行正确了,那么代码也就没有什么问题了,可是java如何运行步骤cmd?接下来,我们就来给大家讲解一下这方面的内容. 1.首先用 ...
最新文章
- 入职五年回顾(八) 2013年3月
- 开挂的 00 后!17 岁「天才少女」被 8 所世界名校录取,最终选择 MIT 计算机系...
- 如何编写数据库存储过程?
- VC++6中的一些快捷键(陆续补充中。。。)
- neroLinux3.x的序列号
- Ascll字符串转换到二进制字符串
- 基于JAVA+SpringMVC+Mybatis+MYSQL的公寓租赁系统
- 清明节,如何用代码让网页变灰
- linux c++ 输出到终端,如何将彩色文本输出到Linux终端?
- 视觉SLAM十四讲_4-相机模型和非线性优化
- GridView中设置DataFormatString无效的解决方法.
- 微信小程序调用域名服务器的服务
- Win:在 Windows Server 中的 NIC Teaming
- Oracle11g64位安装教程
- 论文笔记:Improving Conversational Recommender Systems via Knowledge Graph based Semantic Fusion(KDD2020)
- UVALive - 4987 Evacuation Plan
- 计算机网络基础学习笔记
- 程序员:迟到1分钟罚300,加班却视而不见,月底工资让人寒心
- 《Web全栈工程师的自我修养》浓缩笔记(上)
- 内存读数据和磁盘读数据的区别
热门文章
- 容器技术Docker K8s 28 容器服务ACK基础与进阶-弹性伸缩
- 易筋SpringBoot 2.1 | 第十三篇:SpringBoot综合应用多个DataSoure
- android开发第一个程序,Android开发入门之第一个android程序
- ppocr 源码阅读:ppocr.modeling.architecures 之build_model模块
- 深度神经网络的正则化
- 简述deque容器的插入删除原理
- jar命令成功完成 java -jar 命令却提示“没有主清单属性”!
- android studio for android learning (二十八) android基础知识
- 不变子空间与线性变换的矩阵之间的关系
- oracle数据库第十一章答案,[转载]《互联网数据库》网上作业练习题10-11章答案...