标签:extern 乐观锁 构造方法 英文 inf 公有 thread nta 并发
使用Tab缩进。(I)
每行80字符。(I)
if,for,while语句只有单句时,如果该句可能引起阅读混淆,需要用" {"和"}"括起来,否则可以省略。
//错误,需要使用花括号{}括起来
if (condition) if(condition) doSomething(); else doSomething();
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长;(I)
枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开;(I)
各层命名规约:
A) Service/DAO层方法命名规约 (I)
1) 获取单个对象的方法用findBy做前缀。(I)
2) 获取多个对象的方法用list做前缀,
3) 如果是查询用search做前缀。
4) 获取统计值的方法用count做前缀。
5) 插入的方法用save(推荐)或insert做前缀。
6) 删除的方法用remove(推荐)或delete做前缀。
7) 修改的方法用update做前缀。
B) 领域模型命名规约 (I)
1) 数据对象:xxx,遵循驼峰,xxx即为数据表名,例如 User。
2) 数据传输对象:xxxDTO,xxx为业务领域相关的名称。
3) 展示对象:xxxVO,xxx一般为网页名称。
4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。
常量定义
常量必须先定义(I)
同等的类型,按public, protected, private的顺序排列。
IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式, 不要使用 windows 格式 (I)
略。
由/*...*/界定,标准的C-Style的注释。专用于注释已失效的代码。
/* * Comment out the code * String s = "hello"; * System.out.println(s); */
由//界定,专用于注释代码细节,即使有多行注释也仍然使用//,以便与用/**/注释的失效代码分开
除了私有变量外,不推荐使用行末注释。
class MyClass { private int myField; // An end-line comment. public void myMethod { //a very very long //comment. if (condition1) { //condition1 comment ... } else { //elses condition comment ... } } }
注释中的每一个单词都要有其不可缺少的意义,注释里不写"@param name -名字"这样的废话。
如果该注释是废话,连同标签删掉它,而不是自动生成一堆空的标签,如空的@param name,空的@return。
如果方法允许Null作为参数,或者允许返回值为Null,必须在JavaDoc中说明。
如果没有说明,方法的调用者不允许使用Null作为参数,并认为返回值是Null Safe的。
/** * 获取对象. * * @ return the object to found or null if not found. */ Object get(Integer id){ ... }
防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
1) 返回类型为包装数据类型,有可能是null,返回int值时注意判空。
反例:public int f(){ return Integer 对象}; 如果为 null,自动解箱抛 NPE。
2) 数据库的查询结果可能为null。
3) 集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
4) 远程调用返回对象,一律要求进行NPE判断。
5) 对于Session中获取的数据,建议NPE检查,避免空指针。
6) 级联调用obj.getA().getB().getC();一连串调用,易产生NPE。
3.4 日志
应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(I)
SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式,(I)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么往上 抛。正例:logger.error(各类参数或者对象toString + "_" + e.getMessage(), e); (I)
避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可(I)
所有的覆写方法,必须加@Override 注解(I)
不能使用过时的类或方法
Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals ,正例: "test".equals(object); 反例: object.equals("test"); (I) 说明:推荐使用java.util.Objects#equals (JDK7引入的工具类)
所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较 (I)
定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中 (I)
POJO 类必须写 toString 方法。使用 IDE 的中工具:右键> generate->toString 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。 说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排 查问题。修改默认模板方法 (I)
当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读
类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法
字符串的联接方式,使用 StringBuilder 的 append 方法进行扩展 (I)
final 可提高程序响应效率,声明成 final 的情况 ,
a>不需要重新赋值的变量,包括类属性、局部变量
b>对象参数前加final,表示不允许修改引用的指向
c>类方法确定不允许被重写
在 if/else/for/while/do 语句中必须使用大括号,即使只有一行代码,避免使用 下面的形式:if (condition) statements;
循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)
接口入参保护,这种场景常见的是用于做批量操作的接口
方法中需要进行参数校验的场景,
调用频次低的方法
执行时间开销很大的方法,参数校验时间几乎可以忽略不计,但如果因为参数错误导致,中间执行回退,或者错误,那得不偿失
需要极高稳定性和可用性的方法
对外提供的开放接口,不管是RPC/API/HTTP接口
敏感权限入口
方法中不需要参数校验的场景
极有可能被循环调用的方法,不建议对参数进行校验。但在方法说明里必须注明外部参数检查
底层的方法调用频度都比较高,一般不校验。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。一般 DAO 层与 Service 层都在同一个应用中,部署在同一 台服务器中,所以 DAO 的参数校验,可以省略
被声明成private只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参 数已经做过检查或者肯定不会有问题,此时可以不校验参数
在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度
注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够 取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后 取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法
获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime() ,
如果想获取更加精确的纳秒级时间值,用 System.nanoTime()。在 JDK8 中,针对统计 时间等场景,推荐使用 Instant 类
任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁 (I)
Iterator<String> it = a.iterator(); while(it.hasNext()){ String temp = it.next(); if(删除元素的条件){ it.remove(); } }
集合初始化时,尽量指定集合初始值大小,说明:ArrayList尽量使用ArrayList(int initialCapacity) 初始化
使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历
利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains 方法进行遍历、对比、去重操作
获取单例对象需要保证线程安全,其中的方法也要保证线程安全,资源驱动类、工具类、单例工厂类都需要注意
创建线程或线程池时请指定有意义的线程名称,方便出错时回溯
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为
static,必须加锁,或者使用 DateUtils 工具类。
正例:注意线程安全,使用 DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd"); } };
说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter 代替 Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。
并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在 数据库层使用乐观锁,使用 version 作为更新依据。说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次 数不得小于 3 次。
多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获 抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题
使用Eclipse与 Inellij IDEA的代码校验功能已经排除了很多问题。
uap关于list的遍历
List result = biz.getList(); if(result!=null){ for(int i=0;i<CheckList.checkListSize(result);i++){ // TODO } }
addWhere("param=123");
改成
addWhere("param","=","123");
标签:extern 乐观锁 构造方法 英文 inf 公有 thread nta 并发
原文地址:https://www.cnblogs.com/ephemeral/p/9673371.html