每一个人都有属于自己的一片森林,迷失的人迷失了,相逢的人会再相逢。
编写优雅的代码
面向对象
1.构造器参数太多怎么办?
如果参数很多:会导致构造方法非常多,拓展性差,可读性差,代码也难以编写。
用JavaBeans模式:get/set
不能一行构造,多行才能完成,有线程安全问题,也要确保一致性。
用builder模式:
用于:
5个或者5个以上的成员变量;
参数不多,但是未来会拓展。
优势:
如果有很多参数是可选的,代码易于阅读和编写,比javabeans更安全。
2.不需要实例化的类,应该构造器私有
单例模式。
好出:防止使用者new出多个实例。
3.不要创建不必要的对象
1.避免无意间创建不必要的对象,如:自动装箱(long、Long)
2.可以在类中多个实例间重用的成员变量,尽量使用static
4.避免使用终结方法
Finalizer方法,jdk不能保证何时执行,也不能保证一定会执行,如果确实有需要释放的资源使用try、finally。
5.使类和成员的可访问性最小化
封装,模块之间的解耦
微服务-思想一样。
6.使可变性最小化
如:类不可变,比可变的类更加易于设计,实现,使用,不容易出错,更加安全。
常用手段:
所有的域final、私有化、不提供任何可以修改对象状态的方法
7.复合优先于继承
复合是在类中增加一个私有的域,引用类的一个实例。这样的话就避免依赖类的具体实现。
继承容易破坏父类封装性,并且会使子类的实现依赖于父类。
判断使用复合还是继承的标准:实际的使用中,如果你肯定父类的子类,就使用继承。如果不是很肯定,就是用复合。(简单来说:你很知道父类的东西,你就使用继承。如果把握不准,就使用复合。这样安全系数会高一点)。
8.接口优先于抽象类
接口只有方法的申明,抽象类中可以写方法的实现。
Java中都属于单继承(不能继承多个),写一个类可以实现多个接口,灵活性更高。
抽象类,如:有业务方法变化(新增一个接口),抽象类会去实现
接口:就新增一个方法。
方法
9.可变参数要谨慎使用
可变参数可以传入null、0个参数
可变参数,1~多个时,需要做单独的业务控制,代码就不优雅。
10.返回零长度的数组或集合,不要返回NULL
最好不要返回null
JDK提供了零长度的集合。
11.优先使用标准的异常
要尽量追求代码的重用,同时减少类加载的数目,提高类装载的性能。
public class StandardException {
public static void main(String[] args) throws Exception{
//调用者传递的参数不合适。如:你需要一个大于0的数,结果是0,抛这个异常
int count = 0;
if (count <= 0){
throw new IllegalArgumentException("");
}
//接收的对象状态不对
int state = 0;
if(state != 1){
throw new IllegalStateException("");
}
//接收对象为空
Object o = new Object();
if(o == null){
throw new NullPointerException("");
}
}
// 不支持的操作
protected boolean tryAcquire(long arg){
throw new UnsupportedOperationException();
}
}
通用程序设计
12.用枚举代替int常量
所谓的枚举的本质就是一个类,每一个枚举值就是这个枚举的实例。
常量的坑:
1.使用常量容易写错;
2.使用常量容易描述混乱甚至麻烦;
3.其他类在使用常量时,类编译器会把常量的值直接写入字节码中,如果常量有变化,所有相关的类必须要重新编译,否则会有不可预估的错误。
13.将局部变量的作用域最小化
1.在第一次使用的地方进行声明;
2.局部变量都是要自行初始化,如果初始化的条件不满足就不要声明;
好处:减少局部变量表的大小,提高性能;避免局部变量过早使用导致的业务代码编写错误。
14.精确计算,避免使用float和double
float 和 double 在JVM存储的时候,因为要做小数点的存储。有一部分需要做整数处理,一部分做小数处理。所以精度有问题。
15.担心字符串连接的性能
不推荐使用 “sss”+“wwww”;
如果要大量的字符串拼接:stringbuffer,stringbuilder
16.控制方法的大小
一个方法内的东西别太多,很难读,很难维护。