美文网首页代码规范
代码规范笔记

代码规范笔记

作者: 辛rf | 来源:发表于2020-07-10 23:48 被阅读0次

摘自阿里巴巴JAVA开发手册

1.相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。

说明:可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程)正例:publicList<User>listUsers(String type,Long... ids){...}

2.接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。

3.所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。

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

4.关于基本数据类型与包装数据类型的使用标准如下:

1)【强制】所有的POJO类属性必须使用包装数据类型。

2)【强制】RPC方法的返回值和参数必须使用包装数据类型。

3)【推荐】所有的局部变量使用基本数据类型。

说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。

正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。

反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。

4.构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

5.POJO类必须写toString方法。使用IDE中的工具:source>generatetoString

时,如果继承了另一个POJO类,注意在前面加一下super.toString。

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

6.setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,不要增加业务逻辑,增加排查问题的难度。

7.慎用Object的clone方法来拷贝对象。

说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现域对象的深度遍历式拷贝。

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

说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素个数大于实际所需,下标为[list.size()]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。

正例:

List<String> list = new ArrayList<String>(2);list.add("guan");

list.add("bao");

String[] array = new String[list.size()];array = list.toArray(array);

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

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

说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。

String[] str = new String[] { "you", "wu" };

Listlist = Arrays.asList(str);

第一种情况:list.add("yangguanbao");运行时异常。

第二种情况:str[0]="gujin";那么list.get(0)也会随之修改。

10.集合初始化时,指定集合初始值大小。

说明:HashMap使用HashMap(intinitialCapacity)初始化。

正例:initialCapacity=(需要存储的元素个数/负载因子) + 1。注意负载因子(即loaderfactor)默认为0.75,如果暂时无法确定初始值大小,请设置为16(即默认值)。

反例:HashMap需要放置1024个元素,由于没有设置容量初始大小,随着元素不断增加,容量7次被迫扩大,resize需要重建hash表,严重影响性能。

11.使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。

说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。

正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。

12.多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。

13.使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法被执行到,避免主线程无法执行至await方法,直到超时才返回结果。

说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。

14.volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。如果是count++操作,使用如下类实现:AtomicIntegercount=newAtomicInteger();count.addAndGet(1);如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。

15.HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险。

16.在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使空代码。

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

18.不要在finally块中使用return。

说明:finally块中的return返回后方法结束执行,不会再执行try块中的return语句。

19.主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。说明:pk_即primary key;uk_即uniquekey;idx_即index的简称

20.varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

21.字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:

1)不是频繁修改的字段。

2)不是varchar超长字段,更不能是text字段。

22.单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表

23.超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。

说明:即使双表join也要注意表索引、SQL性能。

24.不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。

说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。

25.count(distinctcol)计算该列除NULL之外的不重复行数,注意count(distinctcol1,col2)如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

26.在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。

27.in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。

28.TRUNCATETABLE比DELETE速度快,且使用的系统和事务日志资源少,但TRUNCATE

无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。

说明:TRUNCATETABLE在功能上与不带WHERE子句的DELETE语句相同。

29.@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。

30.所有pom文件中的依赖声明放在<dependencies>语句块中,所有版本仲裁放在<dependencyManagement>语句块中。

说明:<dependencyManagement>里只是声明版本,并不实现引入,因此子项目需要显式的声明依赖,version和scope都读取自父pom。而<dependencies>所有声明在主pom的<dependencies>里的依赖都会自动引入,并默认被所有的子项目继承。

31.高并发服务器建议调小TCP协议的time_wait超时时间。

说明:操作系统默认240秒后,才会关闭处于time_wait状态的连接,在高并发访问下,服务器端会因为处于time_wait的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。

正例:在linux服务器上请通过变更/etc/sysctl.conf文件去修改该缺省值(秒):net.ipv4.tcp_fin_timeout= 30

32.【推荐】调大服务器所支持的最大文件句柄数(FileDescriptor,简写为fd)。

说明:主流操作系统的设计是将TCP/UDP连接采用与文件一样的方式去管理,即一个连接对应于一个fd。主流的linux服务器默认所支持最大fd数量为1024,当并发连接数很大时很容易因为fd不足而出现“opentoomanyfiles”错误,导致新的连接无法建立。建议将linux服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。

33.给JVM环境参数设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM场景时输出dump信息。

说明:OOM的发生是有概率的,甚至相隔数月才出现一例,出错时的堆内信息对解决问题非常有帮助。

34.在线上生产环境,JVM的Xms和Xmx设置一样大小的内存容量,避免在GC后调整堆大小带来的压力。

相关文章

  • 代码规范笔记

    摘自阿里巴巴JAVA开发手册 1.相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。...

  • Markdown 语法笔记

    笔记规范 下面代码块中,表示 Markdown 语法 代码块下方, 则是 Markdown 效果行内代码 标题&段...

  • Google代码规范笔记

    类数据成员 不管是静态的还是非静态的, 类数据成员都可以和普通变量一样, 但要接下划线.

  • Web 端代码规范

    目录 1、代码规范概述 2、代码规范流程搭建 3、代码规范细则 1、代码规范概述 良好的代码规范能够提供软件的可读...

  • 代码规范

    代码规范 1. 概述 欢迎使用前端代码规范, 这里借鉴、引用的是京东前端代码规范。 遵循代码规范的目的在于增强团队...

  • iOS 代码规范篇

    iOS 代码规范篇 iOS 代码规范篇

  • iOS(OC)开发之随感

    1.代码规范 规范很重要!规范很重要!规范很重要! 代码规范的重要性之-为什么谷歌要执行严格的代码编写规范http...

  • 前端学习的基本总结

    目录 1.为什要遵守代码规范 2.css代码规范 3.js代码规范与设计模式3.1 js代码规范3.2 设计模式 ...

  • 乐乎项目优化

    编程: 1、代码规范。架构规范、文件组织规范、命名规范、代码逻辑规范、资源存放。 一、使用cocoapod 二、代...

  • 小肤iOS开发代码规范_v1.0

    For Objective-C , 2018.8.2 Ⅰ.前言Ⅱ.命名规范Ⅲ.代码注释规范Ⅳ.代码格式化规范Ⅴ....

网友评论

    本文标题:代码规范笔记

    本文链接:https://www.haomeiwen.com/subject/wmktsqtx.html