反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC 框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。
public class OrderFactory; public class LoginProxy; public class ResourceObserver;
反例:String key = "Id#taobao_" + tradeId;
cache.put(key, value);
正例:public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}
【强制】 避免通过一个类的对象引用访问此类的静态变量或静态方法 ,无谓增加编译器解析成本,直接用类名来访问即可。
【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
说明:注意 serialVersionUID 不一致会抛出序列化运行时异常。
【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
【强制】POJO 类必须写 toString 方法。使用 IDE 的中工具:source> generate toString 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。
说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排 查问题。
说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。
反例:
String str = "start"; for (int i = 0; i < 100; i++) { str = str + "hello"; } 复制代码
说明:String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象 作为 key 来使用。
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。
反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它 类型数组将出现 ClassCastException 错误。
说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。 String[] str = new String[] { "you", "wu" }; List list = Arrays.asList(str);
第一种情况:list.add("yangguanbao"); 运行时异常。
第二种情况:str[0] = "gujin"; 那么 list.get(0)也会随之修改。
【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。
【推荐】高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:
说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资 源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者 “过度切换”的问题。
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
【推荐】避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。
说明:Random 实例包括 java.util.Random 的实例或者 Math.random()的方式。
正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要编码保 证每个线程持有一个实例。
说明:如果非得使用 if()...else if()...else...方式表达逻辑,【强制】避免后续代码维 护困难,请勿超过 3 层。 正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现, 其中卫语句示例如下:
public void today() { if (isBusy()) { System.out.println(“change time.”); return; } if (isFree()) { System.out.println(“go to travel.”); return; } System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.”); return; } 复制代码
【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
【强制】后台输送给页面的变量必须加$!{var}——中间的感叹号。
说明:如果 var=null 或者不存在,那么${var}会直接显示在页面上。
正例:if (obj != null) {...}
反例:try { obj.method() } catch (NullPointerException e) {...}
【强制】异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。
【强制】对大段代码进行 try-catch,这是不负责任的表现
【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的 内容。
【推荐】防止 NPE,是程序员的基本修养.
【参考】在代码中使用“抛异常”还是“返回错误码”,对于公司外的 http/api 开放接口必须 使用“错误码”;而应用内部推荐异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封 装 isSuccess()方法、“错误码”、“错误简短信息”
【强制】日志文件推荐至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。
【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。
【强制】用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入, 禁止字符串拼接 SQL 访问数据库。
【强制】用户请求传入的任何参数必须做有效性验证。
【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
【强制】 varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text ,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。
【强制】表必备三字段: id , gmt _ create , gmt _ modified 。
【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。
【推荐】利用覆盖索引来进行查询操作,避免回表。说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览 一下就好,这个目录就是起到覆盖索引的作用。
正例:能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种 效果,用 explain 的结果,extra 列会出现:using index。
正例:如果 where a=? and b=? ,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即 可。
【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
【推荐】高并发服务器建议调小 TCP 协议的 time_ wait 超时时间。
【推荐】调大服务器所支持的最大文件句柄数 (File Descriptor ,简写为 fd) 。
【推荐】给 JVM 设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM 场景时输出 dump 信息。
【推荐】在线上生产环境, JVM 的 Xms 和 Xmx 设置一样大小的内存容量,避免在 GC 后调整堆 大小带来的压力。
【参考】服务器内部重定向使用 forward; 外部重定向地址使用 URL 拼装工具类来生成,否则 会带来 URL 维护不一致的问题和潜在的安全风险。
我是蛮三刀把刀,目前为后台开发工程师。主要关注后台开发,网络安全,Python爬虫等技术。
来微信和我聊聊:yangzd1102
Github: github.com/qqxx6661