编程规范
一、格式规范
-
见名知意。包名、类名、变量名、方法名一定要通过命名读懂其意思
-
代码顺序。按照JVM加载该类以及实例化的顺序编码。
遵循 静态变量--> 静态代码块 --> 实例变量 --> 静态方法 --> 实例方法 --> 抽象方法
-
变量的声明范围最小化,能局部就不要实例声明,能实例声明就不要静态声明,最少原则(能延迟到子类的就只在子类中声明)
-
工具类一致用final声明,且为单例,并且只有静态方法,最好是无状态、或者是只读线程安全的类
-
常量类、配置类一致为单例模式
-
静态方法尽量用泛型来泛化
public static <T> T checkIsNull(T t, String errorMsg) { if (t == null) { throw new NullPointerException(errorMsg); } return t; }
-
对于变量尽量使用final来声明
-
合理使用public/protected/private/默认 这四种关键修饰符
二、异常部分
- 非运行时异常一定不要无故在方法内吞掉异常,尽量抛出异常让上层处理。如:IOException
- 运行时异常一般都是程序的问题,尽量在编码的过程规避掉,养成良好的编程习惯。如:NullPointerException/NumberFormatException/IllegalArgumentException/
- 在敲每一个.的时候,考虑可能会不会为空
- 对于可能会抛异常的代码块,要用try/catch/final 来处理,防止发生不可靠的异常执行流程,catch中一定要日志化,且恢复状态变量
三、输入输出规范
- 构造方法。实例中的变量如果不能为空,一定要先校验传入的参数是否合法,防止实例方法中因为没有赋值,抛异常的风险
- 实例方法。对于传入的参数,一定要校验参数的合法性,对于不合法的参数要日志打印错误信息,并尽早结束方法的执行流程
- 方法的返回值。 对于有返回值得方法(尤其是引用类型),在遇到异常时或者提前结束流程的时候一定要返回一个具体的空对象,而不是一个null。
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
//提前判断参数合法化
if (initialCapacity == 0 && maxCapacity == 0) {
//对于非法的参数,返回一个空的对象,而非null
return emptyBuf;
}
validate(initialCapacity, maxCapacity);
return newDirectBuffer(initialCapacity, maxCapacity);
}
四、多线程安全规范
- 对于每个类中的可变变量,考虑会被哪些线程访问到,是否会有线程安全问题
- 哪些代码属于热点代码,热点代码中是否存在线程非安全的风险
- 全局可变变量一定注意线程安全问题
- 容器类部分,如果涉及到线程安全问题,使用并发容器,禁止使用同步容器。
- 对于读多写少的可以使用读写锁,以降低锁的时间
- CopyOnWriteXXX 容器一定要注意内存问题,以及效率问题。 当数据量非常大的时候,执行更新操作效率非常低,如CopyOnWriteArrayList 中放入50w数据,再去add数据,可能会非常慢。
- 尽量少使用类级别的锁,如在静态方法中加锁、或者
synchronized (XXX.class){
//此块为类级别的锁,效率低
}
五、IO流关闭规范
- 涉及到IO流的类,一定使用try/catch/final 格式去处理,并在final中关闭流,防止文件句柄资源不能释放。常用的 InputStream/OutputStream/网络IO流/文件IO流
六、可扩展式规范
- 针对接口或者抽象编程,禁止用具体类声明变量
- 接口的参数能用泛化尽可能的用泛化,提高程序的可适用性
七、效率
- 在循环代码块中一定要注意耗时的操作,能提取到外面尽量提取到循环体外面,尤其是多层循环