java编写代码规范
常量和变量
-
直接赋值常量,禁止声明新对象:
- 直接赋值常量值,只是创建了一个对象引用,而这个对象引用指向常量值。
Long i=1L; String s="abc";
-
当成员变量值无需改变时,尽量定义为静态常量
- 在类的每个对象实例中,每个成员变量都有一份副本,而成员静态常量只有一份实例
public class HttpConnection{ private static final long timeout=5L; }
-
尽量使用基本数据类型,避免自动装箱和拆箱
- java中的基本数据类型:double,float,long,int,short,char,boolean,分别对应的包装类Double、Short、Character、Boolean
java支持脚本类型与对象包装类的自动转换,被称为自动装箱和拆箱,都需要CPU和内存的自动装箱和拆箱
-
如果变量的初值会被覆盖,就没有必要给变量赋初值
-
尽量使用函数内的基本类型临时变量:
- 在函数内,基本类型的参数和临时变量都保存在栈(Stack)中,访问速度比较快;对象类型的参数和临时变量的引用都保存在栈(Stack)中,内存都保存在堆(Heap)中,访问速度比较慢,在类中,任何类型的成员变量都保存在堆(Heap)中,访问速度比较慢
-
不可变的静态常量、成员变量,尽量使用非线程安全类
- 不可变的静态常量,虽然需要支持多线程访问,也可以使用非线程安全类。
-
null可以赋值给引用变量,但是不能将null赋给基本类型变量
-
不允许使用任何未经定义的常量
-
包装类型之间的判等用equals而不是==
-
浮点数之间的等值判断
- 基本类型不用==来比较
- 包装数据类型不用equals来判断
-
不能使用一个值为null的引用类型变量来调用非静态方法。
-
不能调用非静态方法来使用一个值为null的引用类型变量,但是可以使用静态方法来使用一个值为null的引用类型变量。
-
在金融计算中必须使用BigDecimal
对象和类
-
禁止使用JSON转换对象
- JSON提供把对象转换为JSON字符串、把JSON字符串转为对象的功能,会影响性能
-
尽量不使用反射赋值对象
- 导致性能下降
-
采用Lambda表达式代替内部匿名类
- Lambda表达式在大多数虚拟机中采用invokeDynamic指令实现,相对于匿名内部类在效率上会更高一些
例子:
List<User> userList=new ArrayList<>(); Collections.sort(userList,(User o1,user o2)->{ Long userId1=o1.getId(); Long userId2=o2.getId(); return userId1.compareTo(userId2); });
-
尽量避免定义不必要的子类
- 多一个类就需要多一份类加载,所以尽量避免定义不必要的子类
-
尽量指定类的final修饰符
- 为类指定final修饰符,可以让改类不可以被继承,如果指定了一个类为final,则该类的所有方法都是fianl的,java编译器会寻找机会内敛的所有final方法,内敛对于提升java运行效率有很大的作用。
PS:使用Spring的AOP特性时,需要对Bean进行动态代理,如果Bean类添加了final修饰,会导致异常
-
不在foreach循环里进行元素的remove/add操作,remove元素可以使用Iterator方式,如果并发操作,需要对Iterator对象加锁。或者将去取出放入一个集合中然后删除或者增加这个集合。或是使用java8新增方法
-
使用equals时,应使用常量或确定有值得对象来调用equals,避免空指针异常,另外可以使用java.util.Objects的equals方法来避免空指针异常
- 或者使用StringUtils工具类进行判断
-
成员变量不要使用public修饰,尽量使用private修饰,如果需要被子类继承,可以用protected修饰
- 如果成员变量设置为public,那么每个调用者都可以读写它,但如果以private配合getter/setter的形式访问时,就可以达到“不准访问”,“只读访问”,“读写访问”,“只写访问”
class Interviewer {
private Candidate candidate;
public Interviewer (Candidate candidate) {
this.candidate = candidate;
}
public Candidate getCandidate() {
Candidate candidate = new Candidate(this.candidate.getName());
return candidate;
}
}
方法
- 把跟类成员变量无关的方法声明成静态方法
- 静态方法的好处就是不用生成类的实例就可以直接调用,静态方法不再属于某个对象,而是属于它所在的类,只需要通过其类名就可以访问,不再需要消耗资源去反复创建对象。即便在类内部的私有方法,如果没有使用到类成员变量,也可以声明为静态方法。
- 尽量使用基本数据数据类型作为方法参数类型、返回值类型,避免不必要的装箱、拆箱和空指针判断
- 协议方法参数值、返回值非空,避免不必要的空指针判断
- 协议编程:可以@NonNull和@Nullable标注参数,是否遵循全凭调用者自觉
- 尽量避免不必要的函数封装
- 方法调用会引起入栈和出栈,导致消耗更多的CPU和内存
表达式
- 尽量使用移位来代替正整数乘除
- 尽量使用StringBuilder进行字符串拼接
- 不要使用“” +转换字符串,使用String.valueOf
数组
- 不要使用循环拷贝数组,尽量使用System.arraycopy拷贝数组
- 集合转换为类型T数组时,尽量传入空数组T【0】
- 将集合转化为数组有两种方式:toArray(new T【n】)和toArray(new T[0])。
- 集合转化为Object数组时,尽量使用toArray()方法
集合
- 初始化集合时,尽量指定集合大小
- 尽量使用Arrays.asList转化数组为列表
- 直接迭代需要使用的集合
- 不要使用size方法检测空,必须使用isEmpty方法检测空
- 非随机访问的List,尽量使用迭代代替随机访问
- 尽量使用HashSet判断值存在
异常
-
尽量避免在finally语句块中出现运行时错误,可以适当添加判断语句来增加程序的健壮性。
-
try、finally和return:
- try不管有没有return finally都会执行:避免了在try中return而没有关闭相关资源的操作。
- try中return的情况下,会将return的值存放到一个本地变量中,finally语句即时对其进行了改变也无法改变返回值
- 但是要是finally中也有return语句的话,会忽略try中的return语句。
缓冲区
- 尽量重复使用同一缓冲区