学习总结

本次开发编码规范手册的变更,相比上一版本存在较多的变化。
主要集中在,对于其中的原理有了更深层次的追踪和了解:
1. 集合元素章节对于集合元素的处理上容易出现问题的地方。
2. 新增敏捷模式下,对设计文档的要求(哪些必须有,哪些可以无)
3. 对于数据库查询语句的规约,索引的使用规约
4. 数据库字段命名规则,库表字段命名
5. 单元测试的要求
6. 并发处理JDK8

编程规约

9. 包名统一小写,且使用单数形式,类名可以使用复数形式
例:
com.alibaba.ai.util.MessageUtils
10.避免在子父类使用相同的成员变量命名,不同代码块的局部变量相同命名,造成可读性降低
13.标识类型的名词放在词尾,以提升辨识度。
例:
startTime workQueue nameList THREAD_COUNT

常量定义

3.不要一个常量类维护所有的常量,按功能归类,分开维护
4.常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量
1) 跨应用共享:放置于二方库jar包中的constant目录下
2) 应用内共享常量:放置于一方库的constant目录下
3) 子工程内共享常量:当前子工程的constant目录下
4) 包内共享常量:即在当前包下单独的constant目录下
5) 类内共享常量:直接在类内部常量定义 private static final
5.如果变量仅在一个固定范围内变化,使用enum类型来定义。
个人深入:
如果此字符串经常被使用,在给类的成员变量赋值时,使用String.intern()来降低内存使用。

代码格式

4. 任何二目、三目应算符的左右两边都需要一个空格。运算符包括=、逻辑运算符 || && 运算符 + - * 、
7.类型强制转换时,右括号与强制转换值直接不需要任何空格隔开。
例:
long first = 10000000000L;
int second = (int)first +2;
8.换行规则
1) 第二行相比第1行缩进4个空格,从第三行起不再缩进
2) 运算符与下文一起换行。
3) 方法的点符号与下文一起换行。
4) 多参数换行时,逗号不换行
5) 前括号不换行
11. 单个方法的总行数尽量不超过80行,每行不超过120字符
13.不同逻辑、语义、业务间最多插入一个空行分隔提升可读性。

OOP规则

2.所有复写方法,必须加@orerride注解 (IDEA会检测)
4.过时方法,及时清理或加上@Deprecated注解
5.新增代码不能使用依赖包中的过时方法
6.使用equals方法时,需常量在前,如果都为变量,可使用google的空指针包装类进行判断
7. 所有整形包装类对账之间的值比较,全部使用equals方法进行比较
8. 浮点数之间的等值判断 ,不能使用==来比较,包装数据类型不能使用equals(原文是否有错,应该是包装数据类型不能使用==吧,要使用equals)
反例:
float a = 1.0f -0.9f
float b = 0.9f -0.8f
if (a == b) {预期进入此代码块,实际上为false
}
正例1:
如果在一个误差范围内,则认为相等
float a = 1.0f -0.9f
float b = 0.9f -0.8f
float diff = 1e-6fif (Math(a-b) < diff) {成功 -> 进入代码块
}
正例2:
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.9");
BigDecimal a = new BigDecimal("0.8");BigDecimal diffA = a.subtract(b);
BigDecimal diffB = b.subtract(c);if (x.equals(y) {成功 -> 进入代码块
}
9. DO 属性类型要与数据库字段类型相匹配
-> 原来使用过Mybatis的类型映射String -> int , int -> String 目前看起来不太符合规范
10. 为了防止精度损失,精致使用构造方法BigDecimal(double),最多到BigDecimal(float)
示例:
BigDecilaml g = new BigDecimal(0.1f); 实际值为:0.10000000149
正例:
使用String的方式,Double的toString方法会按照double的实际表达精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = new BigDecimal.valueOf(0.1);
11. RPC及数据POJO类,所有属性使用包装数据类型,局部变量使用基础类型。
12. 所有DO / DTO /VO 等数据类初始化时,不要设定任何存在可能被赋值的属性有默认值。
14.构造方法不能有任何业务逻辑,业务逻辑可以使用init方法或者spring的@poststruts进行初始化。
20.setter /getter方法中,不要增加业务逻辑,增加排查问题的难度
22.final可以什么类、成员变量、方法、以及本地变量,下列情况使用final关键字
1) 不允许被继承的类
2) 不允许修改引用的域对象
3) 不允许被覆写的方法
4) 不允许允许过程中重新赋值的局部变量
5) 避免上下文使用同一个变量,使用final可以强制重新定义一个变量,方便更好地进行重构
23 慎用Object 的clone方法进行拷贝对象,如需深拷贝需要重写clone方法

集合处理

1.关于hashCode和equals的处理
1) 覆写了equals,就必须覆写hashCode
2) 因为Set存在的是不重复对象,根据hashCode和equals进行判断,所以Set存储的对象必须覆这两个方法
3) 如果自定义对象作为MAP的key,那么必须覆写hashCode和quals
2. ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常
说明:subList返回的是ArrayList的内部类SubList,并不是ArrayList,而是ArrayList的一个视图,对于SubList子列表的所有操作会最终反映到原列表。(在使用SubList,父List 的增加及删除操作 需要极度谨慎,容易出现ConcurrentModiffcationException )
3. Collections 类返回的对象,如:emptyList()/singletonList()等都是Immutablelist ,不可对其进行田间及删除元素操作。
说明:这一块可以看list的初始化赋值,对于当一个元素都没有的时,被赋值的对象。和添加第1个元素时,生成的对象不是同一个。
5.在subList场景中,**高度注意对原集合元素的增加或删除**,俊辉导致子列表遍历、增加、删除产生concurrentModificationException异常。
6.集合转数组的方法们,必须使用集合的toArray(T[]) array),传入的是类型完全一致、长度为0的空数组。
反例:
直接使用toArray无参方法存在问题,此方法返回值只能是Objectp[]类,若强转其他类型数组会出现ClassCastException错误。
正例:
list<String> list = new ArrayListM<>(2);
list.add("test");
list.add("??");
String[] array = list.toArray(new String[0]);
说明:使用toArray带参方法,数组空间大小的length选择:
1) 等于0 ,动态创建于size相同的数组,性能最好。
2) 小于0 但小于size,重建创建大小等于size的数组,增加GC负担。
3) 等于size,在搞并发情况下,数组创建完成之后,size正在变大的情况下,负面影响与上相同。
4) 大于size,空间浪费,且在sie处插入null值,存在NPE隐患。
7.在使用Collection接口的任何实现类的addAll()方法时,都要对输入的集合参数进行NPE判断。
8.使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合的相关方法,它的add/remove/clear方法会抛出UnsupportedOperatiponException异常。
说明:asList的返回对象时一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只能转换接口,后台的数据任是数组。String[] str = new String[]{"test","???"};List list  = Arrays.asList(str);
情况1:list.add("test");运行时异常。
情况2:str[0] = "xxx" ,会修改list中的值,反之修改list也会修改str[]
4. 泛型通配符<? extends T>用于接收返回的数据,此写法的泛型集合不能使用add方法,<? super T>不能使用get方法,作为借口调用时易出错。
说明:
PECS(Producer Extends Consumer Super)原则:第一、频繁往外读取内容的,适合用<? extends T>。第二、经常往里插入的,适合用<? super T>
个人总结:<? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入。<? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收。? 既不能用于入参也不能用于返参
示例:class Son extends Self extends SuperList<? extends Self> a = new ArrayList<>(); //参数类型上界是Selfa.add(new Son());//error a.add(new Self());//errora.add(new Super());//errora.add(null);//errorSelf s1 = a.get(0); //返回类型是确定的Self类,因为<? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入Super s2 = a.get(0); //Self类型可以用Super接收Son s3 = a.get(0); //error:子类不能接收父类型参数//--------------------------------------List<? super Self> b = new ArrayList<>(); //参数类型下界是Selfb.add(new Son());//ok 只能放入T类型,且满足T类型的超类至少是Self,换句话说,就是只能放入Self的子类型b.add(new Self());//ok 本身类型也可以b.add(new Super());//error 超类不可以b.add(null);//okObject o1 = b.get(0);//返回类型是未知的, 因为<? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收Son o2 = b.get(0);//errorSelf o3 = b.get(0);//errorSuper o4 = b.get(0);//error
5. 在无泛型限制定义的集合赋值给泛型限制的集合时,在使用集合元素时,需要进行instantof判断,避免抛出ClassCastException异常。
反例:
List<String> generics = null;
List notgenerics = new ArrayList(10);
notGenerics.add(new Object());
notGenerics.add(new Integer(1));generics = notGenerics;
String str = generics.get(0);
6. 不要在foreach循环里进行元素的remove/add操作。remove元素需要使用Iterator,如果并发,需要加锁。
正例:
Iterator<String> iterator = list.iterator();while(iterator.hasNest()) {String item = iterator.next();if (删除条件) {iterator.remove();}}
7. 使用entry遍历Map集合的K、V,而不是keySet方式进行遍历。
注:keySet其实是遍历了两次,一次是转为Iterator对象,另一次从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value放到了entry中,效率更高。JDK 8 中可以使用Map.forEach方法。
8. hashMap值空问题
hashTable(ConcurrentHashMap) key value 都不能为空
hashMap key value 都能为null
TreeMap value 可以为null
8. 对常用数据结构的有序性及稳定性整理。
个人:
ArrayList 无序,稳定
HashMap 无序,不稳定
TreeSet 有序,稳定
有序:按照比较规则依次排列。
稳定,每次遍历的元素次序是一定的。
10. 利用Set元素唯一的特征,可以对一个集合快速去重,避免使用list的contains方法进行遍历、对比、去重。

并发处理

1. 创建线程池时,请指定有意义的线程名称,方便出错时,回溯。
正例:
public class UserThreadFactory implements ThreadFactory {private final String namePrefix;private final AtomicInteger nextId = new AtomicInteger(1);UserThreadFactory(String whatFeaturOfGroup) {namePrefix = "From UserThreadFactory's" + whatFeaturOfGroup + "~Worker~";}@Overridepublic Thread newThread(Runnable task) {String name = namePrefix + nexId.getAndIncrement();Thread thread = new Thread(null, task, name, 0, false);return thread;}
}
个人:方便日志排查
2. 线程资源必须通过线程池提供,不允许在应用自行显示创建线程。
个人:
?如果使用fork join框架怎么办
4. 线程池创建使用Executors去创建会存在问题,应用通过ThreadPoolExecutor的方式去创建。
个人:
对于ThreadPoolExecutor的构造方法里,阻塞队列的初始化(长度设定)、运行模型、核心线程数、最大线程数等参数的设置应该有明确的了解
5. SimpleDateFormat 是线程不安全,如定义为静态共享,则需要加锁,或使用类似threadLocal方式去保证线程安全。
说明:
JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat。
个人:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate date = LocalDate.parse("2017 06 17", formatter);
System.out.println(formatter.format(date));
6. 必须回收自定义的ThreadLocal变量,尽量在代理中使用try-finally块进行回收。
7. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁。能锁区块,就不要锁整个方法体。能用对象锁,就不要用类锁。
个人:锁粒度 尽量小 尽量使用并发包下的数据结构。
8. 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁(循环等待 + 请求和保持条件)。
例如:A线程获取锁顺序为 A C B  ,那么B线程要获取 B C 资源时,也应该先B后C。
个人:
死锁的原因:
互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, ..., pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, ..., n-1),Pn等待的资源被P0占有,如图2-15所示。
9. 在使用阻塞等待获取锁的方式中,必须在try代码块之外,并且在加锁方式与try代码块之间没有可能抛出异常的方法调用,避免加锁成功后,在finally中无法解锁,或尚未获取锁调用解锁会产生的IllegalMonitorStateException异常。
正例:
Lock lock  = new XxxLock();
// ..
try {lock.lock();
} catch (Exception e) {// 结束return;
}
try {doSomething();
} finally {lock.unlock();
}
反例:
参看原文
10. 使用非阻塞尝试机制来获取锁的方式中,进入业务块之前,必须先判断是否持有锁,防止因释放锁时,造成的未申请到锁而抛出的IllegalMinitorStateException 异常。
11. 为防止同一记录并发修改,需要加锁,要么应用层加锁,要么缓存加锁,要么数据库使用乐观锁(通过Compare And Update)以Version作为更新依据。
12. Timer多个TimeTask一个子任务抛出异常,其他任务会停止。
个人:不使用TImer类进行定时任务调度了,推荐使用基于spring的quartz框架 或JDK 7?8自带的ScheduledExecutorService来进行定时任务的调度。
13. 资金相关金融敏感信息,使用悲观锁。
账户锁 (基于缓存/数据库)
14. CountDownLatch使用时,子线程需要保证countDown方法被执行到。
个人:
try {} catch(Exception e) {} finally {countDownLatch.countDown();
}
15. 随机数的Random实例在多线程下存在性能问题。Math.random() 和 Random类
正:使用JDK7 ThreadLocalRandom
另外:部分需要安全要求的随机数,使用java.security.SecureRandom替换java.util.Random
16. 单例类的双重检查锁,变量名需要申明为volatile
17. volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是是多写,统一无法解决线程安全。
18. HashMap在容量不够进行resize时,由于高并发可能出现死链,导致CPU飙升,在开发过程中使用其他数据结构或加锁来避免此风险。
个人:在能够确保HashMap 的size情况下,初始化后不发生resize就不会出现该问题。
19. ThreadLocal对象使用static修饰时,只在类初始化时有一份副本,所有类的对象都只能操作只一份副本。
个人:这样使用不就偏离了ThreadLocal 的应用场景,应该不会有这样用的场景吧。

后续待做 (TODO)

控制语句

异常及日志

日志规约

单元测试

安全规约

MySQL

工程结构

设计规约

阿里java开发规范学习笔记 (V1.5华山版)相关推荐

  1. sonarqube中怎么添加阿里java开发规范

    这篇文章给大家介绍sonarqube中怎么添加阿里java开发规范,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助. 1.拉取sonar-pmd源码,切换到3.2.1.修改pom文件 ...

  2. 阿里巴巴java开发规范学习

    目录 一.编程规约 1.1 命名风格 1.2 常量定义 1.3 代码格式 ​1.4 OOP规约 1.5 集合处理 二.异常 三.MYSQL数据库 3.1 建表规约 3.2 索引规约 3.3 SQL语句 ...

  3. 在线阅读-阿里Java开发手册最强版本【泰山版】

    前言 <Java 开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一 线实战的检验及不断完善,公开到业界后,众多社区开发者踊跃参与,共同打磨完善,系统化地整理 成 ...

  4. “华为云企业级Java编程规范”学习笔记

    一."Java基础语句"编程规范 Switch 语句要有defualt分支,除非Swich的条件变量是枚举类型; 多条件分支语句最后应包含一个else分支; 二."类的使 ...

  5. 阿里巴巴java开发规范Idea插件使用手册

    插件官方下载地址: https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines/versions 插件包是下载的 ...

  6. 阿里云HaaS100物联网开发板学习笔记(三)轻应用初步--用js让小灯闪烁起来

    摘要:能让JavaScript应用运行在haas100开发板上,这实在是太酷了,这种方式被阿里云称之为"轻应用".本文带各位从零开始,先了解啥是轻应用,然后搭建环境,再一步步将一个 ...

  7. 阿里python开发规范手册_阿里巴巴泰山版《Java 开发者手册》,也是一份防坑指南...

    我是风筝,公众号「古时的风筝」,一个不只有技术的技术公众号,一个在程序圈混迹多年,主业 Java,另外 Python.React 也玩儿的 6 的斜杠开发者. Spring Cloud 系列文章已经完 ...

  8. Java开发规范(阿里+腾讯)

    如何适应企业的标准化开发? 文章目录 前言 腾讯开发规范整理(精简) 阿里开发规范整理(精简) 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越 ...

  9. 阿里的Java开发规范插件验证

    阿里最近有点"烦",但是作为技术人,更多关注的还是技术层面,其他的就交给有关机构和时间来证明. 最近有项工作借鉴了阿里的Java开发规范,为了能让其落地,需要验证方案,而这个Jav ...

最新文章

  1. JavaScript的主要功能
  2. MDT2010新功能(15)——完成部署后操作
  3. Socket通信总结(附C++实现)
  4. LeetCode 53. 最大子序和(Maximum Subarray)
  5. mysql事务总结_MySQL数据库和相关事务总结
  6. Android实现拍照并存储功能,Android实现拍照及图片显示效果
  7. @RequestBody、@ResponseBody的具体用法和使用时机
  8. 有多少种 “图片格式”?
  9. 剑指offer面试题32 - III. 从上到下打印二叉树 III(二叉树)(BFS)
  10. 对比了解Grafana与Kibana的关键差异
  11. 计分器 java_非常实用的java语言自动答题计时计分器[Java代码]
  12. 智能网关路灯杆智慧照明解决方案
  13. 我在b站上推荐一个看小电影的网站,结果被骂了
  14. 亚马逊云科技 Build On -轻松搭建咖啡点单系统
  15. ssb的matlab仿真,线性调制AM、DSB、SSB的MATLAB仿真代码
  16. java excel 导入 加校验_【JavaWeb】导入Excel并进行校验
  17. html 渐变透明写法,css实现透明渐变特效的示例代码
  18. c语言中fl,用C语言操作SPMC75内部FLSASH.doc
  19. 优秀的管理者都需要做好这四点
  20. 别被“选择大于努力”骗了!曾经我最成功的事是选了程序员做职业,如今却一败涂地。...

热门文章

  1. 编写Windows服务程序,将Python作为Windows服务启动
  2. 彩旗飘飘 彩灯烁烁的桥
  3. (附源码)计算机毕业设计ssm个性化旅游线路推荐系统
  4. AbortController-中止请求
  5. 模拟量的输入和输出问题及选型
  6. 电子实训与毕业设计开放式训练装置
  7. 30岁哥大计算机博士生遇刺身亡!论文刚被顶会接收,曾留学中国
  8. 计算机二级word安装包,是否有word 2010安装包,计算机二级需要,怎么安装不了呢?...
  9. 【R语言 数据挖掘】R语言如何做关联规则?
  10. MTCNN中的IOU详解