多线程并发
多线程下的Random随机数
避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一 seed 导致的性能下降。JDK7推荐ThreadLocal优化,JDK7推荐使用ThreadLocalRandom。
SimpleDateFormat 和 DatetimeFormatter
SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用ThreadLocal,或者使用 DateUtils 工具类。如果是 JDK8 的应用,可以使用 instant 代替 Date,Localdatetime 代替 Calendar, Datetimeformatter 代替 Simpledateformatter。
双重检查锁和volatile关键字
双重检查锁的问题:初始化Singleton 和 将对象地址写到instance字段 的顺序是不确定的。在某个线程new Singleton()时,在构造方法被调用之前,就为该对象分配了内存空间并将对象的字段设置为默认值。此时就可以将分配的内存地址赋值给instance字段了,然而该对象可能还没有初始化;此时若另外一个线程来调用getInstance,取到的就是状态不正确的对象。
在jdk1.5之后的版本中,可以将instance设置为volatile使双重检查锁生效。
public class Singleton {
private static volatile Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Mybaits
{} 和 ${}的区别
#{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号
${ }是字符串替换, MyBatis在处理${ }时,它会将sql中的${ }替换为变量的值,传入的数据不会加两边加上单引号。
使用${ }会导致sql注入,不利于系统的安全性!
杂项
包装类型缓存问题
Integer a = 1228;
Integer b = 1228;
System.out.println(a == b); //false
System.out.println(a.equals(b)); //true
Equals判定
使用Equals判定时应将常量放在前面,变量放在后面。
if(CONSTANT_A.equals("AAA")){
}
JDK7之后推荐使用Objects.equals()方法。Objects.equals()逻辑如下:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
浮点数和BigDecimal
浮点数在计算机中是无法精确表示的,如遇到货币等精确值时应使用BigDecimal
构造BigDecimal参数时应使用String,而非double或float类型,如应使用new BigDecimal("0.005")
而不是new BigDecimal(0.005)
资金类运算,一般情况下,应以加、减法为主,慎用乘、除法。并注意核对,防止误差,保持账平。例如:“将100.00平分3份”的场景,若每份33.33的话,会有误差
Bean Validation 中内置的校验规则
Hibernate Validator
注解 | 作用 |
---|---|
@CreditCardNumber(ignoreNonDigitCharacters=) | 被注释的字符串必须通过 Luhn 校验算法,银行卡,信用卡等号码一般都用 Luhn 计算合法性 |
@Currency(value=) | 被注释的 javax.money.MonetaryAmount 货币元素是否合规 |
@DurationMax(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=) | 被注释的元素不能大于指定日期 |
@DurationMin(days=, hours=, minutes=, seconds=, millis=, nanos=, inclusive=) | 被注释的元素不能低于指定日期 |
@EAN | 被注释的元素是否是一个有效的 EAN 条形码 |
@Length(min=, max=) | 被注释的字符串的大小必须在指定的范围内 |
@LuhnCheck(startIndex= , endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=) | Luhn 算法校验字符串中指定的部分 |
@Mod10Check(multiplier=, weight=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=) | Mod10 算法校验 |
@Mod11Check(threshold=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=, treatCheck10As=, treatCheck11As=) | Mod11 算法校验 |
@Range(min=, max=) | 被注释的元素必须在合适的范围内 |
@SafeHtml(whitelistType= , additionalTags=, additionalTagsWithAttributes=, baseURI=) | classpath中要有jsoup包 |
@ScriptAssert(lang=, script=, alias=, reportOn=) | 检查脚本是否可运行 |
@URL(protocol=, host=, port=, regexp=, flags=) | 被注释的字符串必须是一个有效的url |