阿里巴巴Java开发手册阅读笔记 [复制链接]

2019-11-8 11:47
shareiOS 阅读:594 评论:0 赞:0
Tag:  阿里巴巴 Java

一、编程规约

(一)命名风格

  • 【强制】POJO 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。

反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC
框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

  • 【推荐】如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。

public class OrderFactory;

public class LoginProxy;

public class ResourceObserver;

(二)常量定义

  • 【强制】不允许任?#25991;?#27861;值(即未经定义的常量)直接出现在代码中。

反例:String key = "Id#taobao_" + tradeId;

cache.put(key, value);

  • 【推荐】如果变量?#21040;?#22312;一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。

正例:public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6),
SUNDAY(7);}

(三)代码格式

(四)OOP 规约

  • 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
  • 【强制?#23458;?#37096;正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的?#38470;?#21475;或者新服务是什么。
  • 【强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。

说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer值可以直接使用==进?#20449;?#26029;,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进?#20449;?#26029;。

  • 【强制】序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值。

说明:注意 serialVersionUID 不一致会抛出序列化运行?#24065;?#24120;。

  • 【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
  • 【强制】POJO 类必须写 toString 方法。使用 IDE 的中工具:source> generate toString
    时,如果?#22363;?#20102;另一个 POJO 类,注意在前面加一下 super.toString。

说明:在方法执?#20449;?#20986;异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排
查问题。

  • 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

说明:反编译出的字节码文件?#20801;?#27599;次循环都会 new 出一个 StringBuilder 对象,然后进行
append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

反例:

(五)集合处理

  • 【强制】关于 hashCode 和 equals 的处理,遵循如下规则: 1) 只要重写 equals,就必须重写 hashCode。 2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进?#20449;?#26029;,所以 Set 存储的对象必须重写这两个方法。 3) 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。

说明:String 重写了 hashCode 和 equals 方法,所以我?#24378;?#20197;非常愉快地使用 String 对象
作为 key 来使用。

  • 【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException
    异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.

说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是
ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

  • 【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()。

反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它
类型数组将出现 ClassCastException 错误。

  • 【强制】使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList
体现的是适配器模式,只是转换接口,后台的数据仍是数组。
String[] str = new String[] { "you", "wu" };
List list = Arrays.asList(str);

第一种情况:list.add("yangguanbao"); 运行?#24065;?#24120;。

第二种情况:str[0] = "gujin"; 那么 list.get(0)?#19981;?#38543;之修改。

  • 【强制】不要在 foreach 循环里进?#24615;?#32032;的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。
  • 【推荐】高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

在这里插入?#35745;?#25551;述

(六)并发处理

  • 【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

说明:使用线程池的?#20040;?#26159;减少在创建和销毁线程上所花的时间?#32422;?#31995;统资源的开销,解决资
源不足的问题。如果不使用线程池,有可能造成系统创建大?#23458;?#31867;线程而导致消耗完内存或者
“过度切换”的问题。

  • 【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  • 【推荐】避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的?#38405;芟陆怠?/li>

说明:Random 实例包括 java.util.Random 的实例或者 Math.random()的方式。

正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要编码保
证每个线程持有一个实例。

  • ?#38745;?#32771;】volatile 解决多线程内存不可见问题。对于一写多读,?#24378;?#20197;解决变?#23458;?#27493;问题,但是如果多写,同样无法解决线程安全问题。如果是count++操作,使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是 JDK8,推荐使用 LongAdder 对象,比 AtomicLong ?#38405;?#26356;好(减少?#27490;?#38145;的重?#28304;?#25968;)。

(七)控制语句

  • 【推荐】表达异常的分支时,少用 if-else 方式

说明:如果非得使用 if()…else if()…else…方式表达逻辑,【强制】避免后续代码维
护困难,请勿超过 3 层。
正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策?#38405;?#24335;、状态模式等来实现,
其中卫语句示例如下:

(八)注释规约

(九)其它

  • 【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速?#21462;?/li>
  • 【强制】后台输送给页面的变量必须加$!{var}——中间的感叹号。

说明:如果 var=null 或者不存在,那么${var}会直接?#20801;?#22312;页面上。

  • 【强制】注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够
    取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后
    取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。

二、异常日志

(一)异常处理

  • 【强制】Java 类库中定义的一类 RuntimeException 可以通过预先检查进行规避,而不应该 通过 catch 来处理,比如:IndexOutOfBoundsException,NullPointerException 等?#21462;?/span>

正例:if (obj != null) {…}

反例:try { obj.method() } catch (NullPointerException e) {…}

  • 【强制】异常不要用来做流程控制,条件控制,因为异常的处理效?#26102;?#26465;件分支低。
  • 【强制】?#28304;蠖未?#30721;进行 try-catch,这是不负责任的表现
  • 【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请
    将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的
    内容。
  • 【推荐】防止 NPE,是程序员的基本修养.
  • ?#38745;?#32771;】在代码中使用“抛异常?#34987;?#26159;“返回错误码?#20445;?#23545;于公司外的 http/api 开放接口必须
    使用“错误码?#20445;?#32780;应用内?#23458;?#33616;异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封
    装 isSuccess()方法、“错误码”、“错误简短信息”

(二)日志规约

  • 【强制】日志文件推荐至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。
  • 【强制】应用中不可直接使用日志系?#24120;↙og4j、Logback)中的 API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

三、单元测试

  • 【强制】好的单元测试必须遵守 AIR 原则。 说明:单元测试在线上运行时,感觉像空气(AIR)一样并不存在,但在测试质量的保障上, 却是非常关键的。好的单元测试宏观上?#27492;擔?#20855;有自动化、独立性、可重复执行的特点。 A:Automatic(自动化) I:Independent(独立性) R:Repeatable(可重复)

四、安全规约

  • 【强制】隶属于用户个人的页面或者功能必须进行权限控制校验。
  • 【强制】用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入,
    禁止字符串拼接 SQL 访问数据库。
  • 【强制】用户请求传入的任何参数必须做有效性验证。

五、MySQL 数据库

(一) 建表规约

  • 【强制】如果存储的字符串长度?#36127;?#30456;等,使用 char 定长字符串类型。
  • 【强制】表达是与否概念的字段,必须使用 is _ xxx 的方式命名,数据类型是 unsigned tinyint( 1 表示是,0 表示否 ) 说明:任何字段如果为非负数,必须是 unsigned 。 正例:表达逻辑删除的字段名 is_deleted ,1 表示删除,0 表示未删除。
  • 【强制】 varchar ?#24378;?#21464;长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长
    度大于此值,定义字段类型为 text ,独立出来一张表,用主键来对应,避免影响其它字段索
    引效率。
  • 【强制】表必备三字段: id , gmt _ create , gmt _ modified 。 说明:其中 id 必为主键,类型为 unsigned bigint 、单表时自增、步长为 1。 gmt_create,
    gmt_modified 的类型均为 date_time 类型,前者现在时表示主动创建,后者过去分?#26102;?#31034;被
    动更新。
  • 【推荐】字段允许?#23454;比?#20313;,以提高查询?#38405;埽?#20294;必须考虑数据一致。冗余字段应遵循: 1 ) 不是频繁修改的字段。 2 ) 不是 varchar 超长字段,更不能是 text 字段。 正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存
    储类目名称,避免关联查询。

(二) 索引规约

  • 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
  • 【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,
    保证被关联的字段需要有索引。
  • 【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字?#35859;?#31435;索引,根据
    ?#23548;?#25991;本区分度决定索引长度即可。
  • 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
  • 【推荐】利用覆盖索引来进行查询操作,避免回表。说明:如果一本书需要知?#36182;?11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览
    一下就好,这个目录就是起到覆盖索引的作用。

正例:能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种
效果,用 explain 的结果,extra 列会出现:using index。

  • 【推荐】建组合索引的时候,区分度最高的在最左边。

正例:如果 where a=? and b=? ,a 列的?#36127;?#25509;近于唯一值,那么只需要单建 idx_a 索引即
可。

(三) SQL语句

  • 【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的
    标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
  • 【强制】不得使用外键与?#35835;?#19968;?#22411;?#38190;概念必须在应用层解决。 说明:以学生和成绩的关系为例,学生表中的 student _ id 是主键,那么成绩表中的 student _ id则为外键。如果更新学生表中的 student _ id ,同时触发成绩表中的 student _ id 更新,即为?#35835;?#26356;新。外键与?#35835;?#26356;新适用于单机低并发,不适合分布式、高并发集群 ; ?#35835;?#26356;新是强阻塞,存在数据库更新风暴的风险 ; 外键影响数据库的插入速?#21462;?/li>
  • 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

(四)ORM ?#25104;?/p>

  • 【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。

六、工程结构

(一)应用分层

阿里巴巴Java开发手册阅读笔记

在这里插入?#35745;?#25551;述

(二)二方库依赖

(三)服务器

  • 【推荐】高并发服务器建议调小 TCP 协议的 time_ wait 超?#31508;?#38388;。 说明:操作系统默认 240 秒后,才会关闭处于 time_ wait 状态的连接,在高并发访问下,服务器端会因为处于 time _ wait的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。 正例:在 linux 服务器上请通过变更/ etc / sysctl . conf 文件去修改该?#31508;?#20540; ( 秒 ) :
    net . ipv 4. tcp _ fin _ timeout = 30
  • 【推荐】调大服务器所支持的最大文件句柄数 (File Descriptor ,简写为 fd) 。 说明:主流操作系统的设计是将 TCP / UDP 连接采用与文件一样的方式去管理,即一个连接对
    应于一个 fd 。主流的 linux 服务器默认所支持最大 fd 数量为 1024,当并发连接数很大时很
    容易因为 fd 不足而出现“ open too many files ”错误,导致新的连接无法建立。 建议将 linux
    服务器所支持的最大句柄数调高数倍 ( 与服务器的内存数量相关 ) 。
  • 【推荐】给 JVM 设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM 场景?#31508;?#20986;
    dump 信息。
  • 【推荐】在线上生产环?#24120;?JVM 的 Xms 和 Xmx 设置一样大小的内存容量,避免在 GC 后调整堆
    大小带来的压力。
  • ?#38745;?#32771;】服务器内部重定向使用 forward; 外部重定向地址使用 URL 拼装工具类来生成,否则
    会带来 URL 维护不一致的问题和潜在的安全风险。

?#20381;此?#20004;句
您需要登录后才可以评论 登录 | 立即注册
facelist
所有评论(0)
领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:[email protected]

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )

招财童子彩金
我爱南京麻将辅助 捕鱼来了cdkey在哪领取 手机麻将游戏免费下 今天新疆35选7开奖号码 中国足彩网球探比分 网络捕鱼输得倾家荡产 大型填大坑棋牌有哪些 分分十一选五助手 中石油股票行情 单机麻将大全集 26选5开奖查询 高端制造业股票 三肖选一肖中特 心悦吉林麻将下载安装 广西快乐双彩开奖结 好彩1开奖结果直播