Java代码开发规范

java代码规范(适合写程序之前先了解有助于开发协同) 类名应该使用大写字母开头的驼峰命名法。例如,PublicClass。类定义应该包含在一个与类名同名的文件中。例如,PublicClass类的定义应该保存在名为PublicClass.java的文件中。类定义应该包括访问修饰符,通常是public,表示该类可以被其他类访问。如果没有指定访问修饰符,则默认为package-private(即只有在同一包中的类可以访问)。类定义可以包含类级别的变量(称为字段)和方法。字段和方法也应该使用驼峰命名法,并且方法名应该以动词开头。 阅读详情

声明:本文基于《阿里巴巴代码规约-嵩山版》,在自己理解的基础上稍有扩展,希望帮到需要的朋友。

1、POJO 类中的任何布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。

说明:在MySQL 建表约定表达是与否的变量采用 is_xxx 的命名方式,所以,需要在<resultMap>设置从 is_xxx 到 xxx 的映射关系。

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

2、POJO 类中的任何字段,需要遵循驼峰命名方式,不应该首字母为大写。

说明:POJO类中的任何字段,如果首字母为大写(不限定其他字母大写或小写),未遵循驼峰命名的方式,SpringBoot将自动进行转小写。

SpringBoot默认消息转换器为MappingJackson2HttpMessageConverter 

真正执行首字母自动转换的类为com.fasterxml.jackson.databind.util.BeanUtil#okNameForMutator方法

默认转换逻辑为:

①、如果为标准输出,越过get前缀后

       如果第一个字母为小写,直接从小写往后截取到最后原样输出。

       第一个字母、第二个字母都为大写,直接越过get前缀截取到最后原样输出。

       例如:NAME->NAME

       否则,首字母转为小写,后面截取到最后原样输出。

②、如果为优化输出,越过get前缀后

       如果第一个字母为小写,直接从小写往后截取到最后原样输出。

       否则,首字母转为小写,后面截取到最后原样输出。  例如:NAME->nAME

3、不允许任何魔法值(即未经预先定义的常量)直接出现在代码中(先声明,后使用)。

说明:

反例:开发者 A 定义了缓存的 key,然后开发者 B 使用缓存时少了下划线,即 key 是"Id#taobao"+tradeId,导致出现故障

String key = "Id#taobao_" + tradeId;

4、在 long 或者 Long 赋值时,数值后使用大写字母 L,不能是小写字母 l,小写容易跟数字混淆,造成误解。

说明:Long a = 2l; 写的是数字的 21,还是 Long 型的 2?

5、所有的覆写方法,必须加@Override 注解。

说明:getObject()与 get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override 可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。

6、不能使用过时的类或方法。

说明:java.net.URLDecoder 中的方法 decode(String encodeStr) 这个方法已经过时,应该使用双参数decode(String source, String encode)。接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。

7、Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

正例:"test".equals(object);

反例:object.equals("test");

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

说明:推荐使用 JDK7 引入的工具类 java.util.Objects#equals(Object a, Object b)

8、所有整型包装类对象之间值的比较,全部使用 equals 方法比较。

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

Integer a=127;

Integer b=127;

Integer c=128;

Integer d=128;

a==b true
c==d false

扩展:其他基本数据类型的包装类也都有这个缓存池,各类型缓存池范围如下:

 9、浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals来判断。

说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数

反例:
float a = 1.0F - 0.9F;
float b = 0.9F - 0.8F;
System.out.println(a == b);
Float x = Float.valueOf(a);
Float y = Float.valueOf(b);
System.out.println(x.equals(y));
System.out.println(x == y);

false
false
false

正例:
(1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。
float a = 1.0F - 0.9F;
float b = 0.9F - 0.8F;
float diff = 1e-6F;
if (Math.abs(a - b) < diff) {
    System.out.println("true");
}
(2) 使用 BigDecimal 来定义值,再进行浮点数的运算操作。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.compareTo(y) == 0) {
    System.out.println("true");

}

10、BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。

说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。

11、禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。

说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。

如:BigDecimal g = new BigDecimal(0.1F); 实际的存储值为:0.10000000149
正例:优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了
Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = BigDecimal.valueOf(0.1);

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

说明:

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

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

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

说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或

者入库检查,都由使用者来保证。

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

反例:某业务的交易报表上显示成交总额涨跌情况,即正负 x%,

x 为基本数据类型,调用的 RPC 服务,调

用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线-。所以包装数据类型

的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

13、final 可以声明类、成员变量、方法、以及本地变量,下列情况使用 final 关键字:

说明:

1)不允许被继承的类,如:String 类。

2)不允许修改引用的域对象,如:POJO 类的域变量。

3)不允许被覆写的方法,如:POJO 类的 setter 方法。

4)不允许运行过程中重新赋值的局部变量。

5)避免上下文重复使用一个变量,使用 final 关键字可以强制重新定义一个变量,方便更好地进行重构。

14、循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append

操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

反例:
String str = "start";
for (int i = 0; i < 100; i++) {
    str = str + "hello";
}

15、日期格式化时,传入 pattern 中表示年份统一使用小写的 y。

说明:

日期格式化时,yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year(JDK7 之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,返回的 YYYY就是下一年。

正例:表示日期和时间的格式如下所示:

new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

扩展:

时间格式规则:

YYYY 代表 Week Year
yyyy 代表year
MM 代表 月(Month)
dd 当月的天
HH代表24小时制
mm:分,2位
ss:秒,2位
yyyy-MM-dd HH:mm:ss:代表将时间转换为24小时制,例: 2018-06-27 15:24:21
yyyy-MM-dd hh:mm:ss:代表将时间转换为12小时制,例: 2018-06-27 03:24:21

16、不要在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑错误。

说明:

正例:
// 获取今年的天数
int daysOfThisYear = LocalDate.now().lengthOfYear();
// 获取指定某年的天数
LocalDate.of(2011, 1, 1).lengthOfYear();
反例:
// 第一种情况:在闰年 366 天时,出现数组越界异常
int[] dayArray = new int[365];
// 第二种情况:一年有效期的会员制,今年 1 月 26 日注册,硬编码 365 返回的却是 1 月 25 日
Calendar calendar = Calendar.getInstance();
calendar.set(2020, 1, 26);
calendar.add(Calendar.DATE, 365);

17、使用枚举值来指代月份。如果使用数字,注意 Date,Calendar 等日期相关类的月份month 取值在 0-11 之间。

说明:参考 JDK 原生注释,Month value is 0-based. e.g., 0 for January.

正例:

Calendar.JANUARY,Calendar.FEBRUARY,Calendar.MARCH 等来指代相应月份来进行传参或比较。

18、必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用 try-finally 块进行回收。

说明:

正例:
objectThreadLocal.set(userInfo);
try {
    // ...
} finally {
    objectThreadLocal.remove();
}

19、关于 hashCode 和 equals 的处理,遵循如下规则:

1)只要覆写 equals,就必须覆写 hashCode。

2)因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须覆写这两种方法。

3)如果自定义对象作为 Map 的键,那么必须覆写 hashCode 和 equals。

说明:String 因为覆写了 hashCode 和 equals 方法,所以可以愉快地将 String 对象作为 key 来使用。

20、判断所有集合内部的元素是否为空,使用 isEmpty()方法,而不是 size()==0 的方式。

21、在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要使用含有参数类型为 BinaryOperator,参数名为 mergeFunction 的方法,否则当出现相同 key值时会抛出 IllegalStateException 异常。

说明:参数 mergeFunction 的作用是当出现 key 重复时,自定义对 value 的处理策略。

正例:
List<Pair<String, Double>> pairArrayList = new ArrayList<>(3);
pairArrayList.add(new Pair<>("version", 12.10));
pairArrayList.add(new Pair<>("version", 12.19));
pairArrayList.add(new Pair<>("version", 6.28));
Map<String, Double> map = pairArrayList.stream().collect(
// 生成的 map 集合中只有一个键值对:{version=6.28}
        Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));
反例:
String[] departments = new String[] {"iERP", "iERP", "EIBU"};
// 抛出 IllegalStateException 异常
Map<Integer, String> map = Arrays.stream(departments)
        .collect(Collectors.toMap(String::hashCode, str -> str));

22、在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。

说明:在 java.util.HashMap 的 merge 方法里会进行如下的判断:

if (value == null || remappingFunction == null)
    throw new NullPointerException();
反例:
List<Pair<String, Double>> pairArrayList = new ArrayList<>(2);
pairArrayList.add(new Pair<>("version1", 8.3));
pairArrayList.add(new Pair<>("version2", null));
Map<String, Double> map = pairArrayList.stream().collect(
// 抛出 NullPointerException 异常
        Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));
正例:
Map<Integer,String> personMap= personList.stream().collect(Collectors.toMap(Person::getId, 
person -> Optional.ofNullable(person.getName()).orElse("null"),(key1, key2) -> key2));

23、ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。

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

正例:

ArrayList<Object> list2 = new ArrayList<>(list.subList(0, 1));
System.out.println(list2);

24、使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationException 异常。

说明:因为没有实现这些方法。

反例:

HashMap<String, Integer> map = new HashMap<>();
map.put("key1", 1);
Set set = map.keySet();
set.add("key4");

entrySet() 和 keySet() 和 values()的使用总结:

1、一般只使用它们的迭代器,用于获取所有键值对。
2、除了迭代器,对元素进行操作的方法不建议使用,容易出错。
3、如果要高效遍历key-value,建议使用entrySet(),keySet()也可以做到,但需要通过key来获取value,多增加了一步。
4、获取所有key就使用keySet(),获取所有value就使用values()
5、keySet(),values(),entrySet()返回的集合是没有额外的数据实体的,都依赖于HashMap的数组+链表结构的Entry数据。所以称返回的是视图。

25、在 subList 场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

说明:

ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
List<Integer> subList = arrayList.subList(1, 3);
for (Integer integer : subList) {
    System.out.println(" "+integer);
}
arrayList.remove(0);
for (Integer integer : subList) {
    System.out.println(" "+integer);
}

分析:ArrayList中有个protected transient int modCount = 0;用来记录当前ArrayList被修改的次数。比如add(),remove()等都会导致modeCount增加

ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount同步ArrayList中的modeCount,SubList对象每次再遍历时,会将自己的modeCount与ArrayList的modeCount进行对比,如果两个值不一样就会报异常:ConcurrentModificationException

26、使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。

说明:

反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现
ClassCastException 错误。
正例:
List<String> list = new ArrayList<>(2);
list.add("guan");
list.add("bao");
String[] array = list.toArray(new String[0]);
说明:使用 toArray 带参方法,数组空间大小的 length: 1) 等于 0,动态创建与 size 相同的数组,性能最好。
2) 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。
3) 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与 2 相同。
4) 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患。

27、在使用 Collection 接口任何实现类的 addAll()方法时,都要对输入的集合参数进行NPE 判断。

说明:在 ArrayList#addAll 方法的第一行代码即 Object[] a = c.toArray(); 其中 c 为输入集合参数,如果为 null,则直接抛出异常。

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

说明:

asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配

器模式,只是转换接口,后台的数据仍是数组。

String[] str = new String[] { "chen", "yang", "hao" };

List list = Arrays.asList(str);

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

第二种情况:str[0] = "change"; 也会随之修改,反之亦然。

29、不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

说明:在 ArrayList#addAll 方法的第一行代码即 Object[] a = c.toArray(); 其中 c 为输入集合参数,如果为 null,则直接抛出异常。

正例:
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (删除元素的条件) {
        iterator.remove();
    } }
反例:
for (String item : list) {
    if ("1".equals(item)) {
        list.remove(item);
 } }

30、集合初始化时,指定集合初始值大小。

说明:HashMap 使用 HashMap(int initialCapacity) 初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。

正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即 loader factor)默认
为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值)。
反例:
HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素增加而被迫不断扩容,
resize()方法总共会调用 8 次,反复重建哈希表和数据迁移。当放置的集合元素个数达千万级时会影响程序
性能。

31、使用 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 值组合集合。

32、高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

说明:

33、线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:

Executors 返回的线程池对象的弊端如下:

1)FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

33、SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。

说明:

如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutablethread-safe。

34、【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用 RPC 方法。

35、在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。

说明:Lock 对象的 unlock 方法在执行时,它会调用 AQS 的 tryRelease 方法(取决于具体实现类),如果当前线程不持有锁,则抛出 IllegalMonitorStateException 异常。

正例:
Lock lock = new XxxLock();
// ...
boolean isLocked = lock.tryLock();
if (isLocked) {
    try {
        doSomething();
        doOthers();
    } finally {
        lock.unlock();
} }

36、并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。

说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3 次。

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

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

38、避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一 seed导致的性能下降。

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

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

39、通过双重检查锁(double-checked locking)(在并发场景下)存在延迟初始化的优化问题隐患(可参考 The "Double-Checked Locking is Broken" Declaration),推荐解决方案中较为简单一种(适用于 JDK5 及以上版本),将目标属性声明为 volatile 型,比如将 helper 的属性声明修改为`private volatile Helper helper = null;`。

正例:

正例:
public class LazyInitDemo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized (this) {
                if (helper == null) { helper = new Helper(); }
            }
        }
        return helper;
    }
    // other methods and fields... 
}

40、当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null判断

说明:

反例:如下的代码输出是什么?

public static void main(String[] args) {
    method(null);
}

public static void method(String param) {
    switch (param) {
        // 肯定不是进入这里
        case "sth":
            System.out.println("it's sth");
            break;
        // 也不是进入这里
        case "null":
            System.out.println("it's null");
            break;
        // 也不是进入这里
        default:
            System.out.println("default");
    }
}

41、类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用// xxx 方式。

说明:在 IDE 编辑窗口中,Javadoc 方式会提示相关注释,生成 Javadoc 可以正确输出相应注释;在 IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。

42、所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。

说明:对子类的实现要求,或者调用注意事项,请一并说明。

43、HTTP 请求通过 URL 传递参数时,不能超过 2048 字节。

说明:不同浏览器对于 URL 的最大长度限制略有不同,并且对超出最大长度的处理逻辑也有差异,2048字节是取所有浏览器的最小值。

反例:某业务将退货的商品 id 列表放在 URL 中作为参数传递,当一次退货商品数量过多时,URL 参数超长,传递到后端的参数被截断,导致部分商品未能正确退货。

44、不要在 finally 块中使用 return。

说明:try 块中的 return 语句执行成功后,并不马上返回,而是继续执行 finally 块中的语句,如果此处存在 return 语句,则在此直接返回,无情丢弃掉 try 块中的返回点。

45、用户敏感数据禁止直接展示,必须对展示数据进行脱敏。

说明:中国大陆个人手机号码显示:139****1219,隐藏中间 4 位,防止隐私泄露。

46、用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入,禁止字符串拼接 SQL 访问数据库。

说明:某系统签名大量被恶意修改,即是因为对于危险字符 # --没有进行转义,导致数据库更新时,where后边的信息被注释掉,对全库进行更新。

47、数据库小数类型为 decimal,禁止使用 float 和 double。

说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。

48、表必备三字段:id, create_time, update_time。

说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time, update_time的类型均为 datetime 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。

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

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

50、页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

51、利用覆盖索引来进行查询操作,避免回表。

说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。正例:能够建立索引的种类分为主键索引、唯一索引、普通索引三种,

而覆盖索引只是一种查询的一种效果,用 explain 的结果,extra 列会出现:using index。

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

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

53、当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL,因此使用 sum()时需注意 NPE 问题。

说明:

正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL(SUM(column), 0) FROM table;

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

说明:

正例:1)增加查询分析器解析成本。2)增减字段容易与 resultMap 配置不一致。3)无用字段增加网络消耗,尤其是 text 类型的字段。

55、POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行字段与属性之间的映射。

说明:

参见定义 POJO 类以及数据库字段定义规定,在 sql.xml 增加映射,是必须的。

56、sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。

说明:

#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号,如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id"
  
$将传入的数据直接显示生成在sql中,如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,  如果传入的值是id,则解析成的sql为order by id.

更多优质内容,感兴趣的朋友请移步至个人公众号,谢谢支持😜😜......

公众号:wenyixicodedog

Java编码规范 Java编码规范要求 阅读详情

相关推荐

阿里巴巴Java开发规范:提升代码质量与专业素养

在软件开发过程中,遵循一套统一的编码规范对于提高代码的可读性、可维护性和协作效率至关重要。阿里巴巴作为大型电商平台的代表,其Java开发规范得到了业界的广泛认可和应用。Java集合框架为处理对象集合提供了一套性能优化且类型安全的接口和类。最常用的集合类可以分为以下几类:List:有序集合,允许重复元素。Set:不允许重复元素的集合。Map:存储键值对的集合。

weixin_42126677的博客 532

Java代码编写规范总结

java 代码编写风格规范参考

hiscoming的博客 1万+

用Docker-Compose三节点部署生产级Doris集群:从配置文件到故障转移

本文详细介绍了如何使用Docker-Compose部署一个生产级的三节点Apache Doris集群。内容涵盖从核心架构理解、配置文件编写到集群初始化验证的全过程,并重点讲解了如何实现高可用、数据持久化、健康检查以及故障转移等生产级运维关键点,为中小团队提供了一种在容器化便利性与系统稳定性间取得平衡的可靠部署方案。

kkk56的博客 857

规范:java代码编写规范

比如在项目中不同的类型的业务可能需要上传各种各样的附件,此时就可以定义好不同的一个附件的枚举,来区分不同业务的附件。不要在代码中直接写死,不定义枚举,代码阅读起来非常困难,直接看到数字都是懵逼的。。我们做了这么多的工作,最终也只有跑起来才能够看到效果,所以在maven打包的时候,不要在了,让测试跑起来。如果可以的话,把单元测试加到我们的CI/CD流程中,只有常态化的用起来,才可以真正的产生效果。上面这些只是我在进行代码质量实践时的一些经验,并不适用于所有人或者场景,但是不管我们可以做到多少,怎么做,

为无为,事无事,味无味。 3168

百度无人车ApolloAuto使用入门

1.安装原版ubuntu 14.04 http://www.ubuntu.org.cn/download/alternative-downloads 2.安装对应ubuntu 14.04的indigo版ROS http://wiki.ros.org/indigo/Installation/Ubuntu 3.安装Apollo Kernel https://github.co

ss910的博客 3万+

华为MA5620配置宽带及语音实例

华为EPON配置实例1、公共部分和宽带PPPOE部分用串口用户名密码root/mduadminMA5620E>enableMA5620E#configMA5620E(config)#MA5620E(config)#sysnamebigcow/给设备起名字/****之前为公共部一、建vlan和地址bigcow(config)#vlan100...

weixin_33862041的博客 6348

java开发种规范全集

最近在公司没事,整理了一些开发规范

SkyinEast的博客 3284

第8讲:基于CST PCB Studio的电源完整性仿真(IR Drop + PDN)

本文系统介绍了电源完整性(PI)仿真的两大核心模块:直流IRDrop仿真与交流PDN阻抗仿真。文章详细阐述了两种仿真的原理、算法(PEEC和3DFE-FD)及完整操作流程,包括参数配置、软件实操步骤和常见问题解决方案。IRDrop仿真用于分析直流供电压降问题,PDN仿真则针对高频电源噪声和谐振问题。文中还提供了优化建议和故障排查方法,如调整铜箔厚度、优化电容布局等,为高速数字系统的电源完整性设计提供了全面的技术指导。(149字)

一只豌豆象的博客 240

java软件编程规范_JAVA代码开发规范

一.开发工具规范:1. 开发工具经项目负责人调试后统一确定。2. 开发工具一经确定不允许集成任何非统一插件,若有需要,经项目负责人同意后统一为 项目组成员添加。3. 开发工具的编码格式不允许修改。二.排版规范:1. 关键词(或变量)和操作符之间加一个空格。 例如:int iCont = 1;//操作符和值之间有一个空格。2. 相对独立的代码块与块之间加空行。 例如:两个方法之间需要用空格隔开。3....

weixin_32029863的博客 462

论文阅读:ICLR 2026 Breaking and Fixing Defenses Against Control-Flow Hijacking in Multi-Agent Systems

该论文首先系统阐述了控制流劫持攻击的核心机理。此类攻击通过操纵多智能体系统的编排机制,诱导系统执行非安全操作,进而实现敏感信息窃取。攻击者将恶意指令伪装成环境错误信息,借助可信代理传递至系统编排器,利用"困惑副手"漏洞绕过传统安全防线。该论文指出,现有防御方案如LlamaFirewall所依赖的对齐检查机制存在根本性局限——安全目标与功能需求之间存在不可调和的内在冲突。该论文的核心贡献体现在攻防两个维度。

CSPhD-winston的博客 494

SAPFiori Elements Analytical List Page 概述

ALP(Analytical List Page)是SAP Fiori提供的一种复合页面类型,结合了分析(图表/KPI)与事务(表格/操作)功能,适用于需要分析后立即执行处理的业务场景(如采购价格监控、销售逾期处理等)。其核心价值在于让用户在同一页面完成从数据洞察到事务处理的闭环,减少应用切换带来的效率损耗。 页面结构包含页头KPI标签、交互式图表和明细表格,通过联动过滤、选择同步等机制实现数据钻取与即时操作。支持标准过滤和可视化过滤,并依赖OData注解(SelectionVariant/Presenta

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 271

java代码开发规范_java代码开发规范

一 编码规范1.1 命名规范代码中的命名均不能以特殊字符(如下划线、$#符号)开始或结束。反例: _name / #Object2. 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。反例: toubao / lipei。3. 类名使用UpperCamelCase风格,必须遵从驼峰形式。正例:CommonUtils / BaseVo4. 方法名、参数名、成员变量、局...

weixin_35713233的博客 262

Ubuntu 22.04+/WSL2 中解决 `error: externally-managed-environment` 并成功安装 PyTorch + vLLM 的完整指南

Ubuntu 22.04+/WSL2 因遵循 PEP 668 规范,系统 Python 被标记为“外部管理”,导致直接使用 pip install 安装包时报错 externally-managed-environment。解决方案是创建虚拟环境: 通过 python3 -m venv ~/vllm-env 创建隔离环境 激活环境后安装 PyTorch(CUDA 12.1)和 vLLM 避免使用 sudo pip 或 --break-system-packages,防止破坏系统依赖 关键点: 虚拟环

刘一说的IT专栏 298

JAVA 代码开发规范

一.开发工具规范: 1. 开发工具经项目负责人调试后统一确定。 2. 开发工具一经确定不允许集成任何非统一插件,若有需要,经项目负责人同意后统一为 项目组成员添加。 3. 开发工具的编码格式不允许修改。 二.排版规范: 1. 关键词(或变量)和操作符之间加一个空格。 例如:int iCont = 1;//操作符和值之间有一个空格。 2. 相对独立的代码块与块...

weixin_34419321的博客 100

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

java代码开发规范

Java代码开发规范 1、工程结构 工程分为三个module :sdk、biz、api api依赖biz biz依赖sdk 1.1.api api功能主要是与外部的交互部分,包括向前端提供的接口,向外部提供的RPC服务的实现等。 包分类 主要包括的package包括但不限于: 1.2.biz 业务核心部分,承接上下,联通api层与数据库、外部服务等。 1.3.sdk 对外提供rpc服务的接口、dto以及枚举等,具体实现会放在api层 remote包统一使用 1.0-SNAPSHOT 作为包管理。 re

qq_40338564的博客 7229

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

看看这些Java代码开发规范吧!你好,我好,大家好!

前言: 插曲:提莫的返工时间又、双、叒、叕、延长了!床上—电脑前—饭桌—电脑前—饭桌—床上的生活状态十多天了! 作为一名开发人员,当你接手他人的项目时,且当你阅读他人的代码时,是有没有遇到脑袋充血,感觉Java要把你“送走”的感觉呢?我们在用Java开发技术进行开发前,一定要牢牢恪守Java的开发标准,唯有如此你的Java开发之路才能更为顺畅。而掌握相应的Java开发技巧,则能够让你作业起来...

豆汁 891

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

每日学学Java开发规范,代码格式(附阿里巴巴Java开发手册(终极版))

每次去不同的公司,码不同的代码,适应不同的规范,经常被老大教育规范问题,我都有点走火入魔的感觉,还是要去看看阿里巴巴Java开发规范,从中熟悉一下,纠正自己,码出高效,码出质量。想细看的可以去官网下载,或者下面自取阿里巴巴Java开发手册(终极版)【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果是非空代码块则:(这个会比较常见,很多程序员在快速编码过程中直接if())左大括号前不换行。左大括号后换行。右大括号前换行。

李老头探索的博客 1721

idea自动换行,设置每行代码长度 -阿里巴巴Java开发规范建议

选择File,选择Settings,搜索Code Style,点击Editor下的Code Style,修改:Hard wrap at 设置每行代码长度 columns,勾选Wrap on typing应该是自动换行的意思,ok

shuai的博客 2万+

Java 代码开发规范

本文简要说明了 Java 开发代码相关的强制性规范,各研发人员必须遵守以下规范: 【强制】代码中使用lombok插件 【强制】所有Controller和Service层的类、函数、接口、参数都要有注释 【强制】所有Controller层的接口只做装箱和拆箱及参数传递,不处理任何业务逻辑 【强制】复杂函数内要做简单的TODO说明 【强制】函数和参数的命名要按实际含义...

丶小剩子的博客 338

JAVA代码开发规范

分页查询-page查询-info新增-save修改-update删除-delete查询-query新增-save修改-modify删除-remove查询-select新增-insert修改-modify删除-delete。

weixin_58508767的博客 160

【亲测免费】 阿里巴巴Java开发规范手册:提升代码质量的必备指南

在现代软件开发领域,高质量的代码不仅仅是功能的实现,更是系统稳定性和可维护性的基石。为了帮助Java开发者更好地遵循最佳实践,阿里巴巴集团推出了《阿里巴巴Java开发规范手册》。这份手册是阿里巴巴技术团队多年实战经验的结晶,旨在为开发者提供一套全面、实用的编程规范,从而提升代码质量,减少潜在的故障风险。 ## 项目技术分析 《阿里巴巴Java开发规范手册》涵盖了Java开发的多个关键领域,包括

gitblog_09740的博客 804

【代码规范神器】阿里巴巴Java开发规范插件IDE使用教程

过年生病,闲的无聊,玩玩阿里巴巴Java开发规范插件。开源插件GitHub地址:https://github.com/alibaba/p3c 插件支持IDEA以及Eclipse安装推荐JDK:JDK1.8+http://mp.weixin.qq.com/s/81oBdbNATkkTXShQAfWFJghttp://blog.youkuaiyun.com/jiashuai94/article/details/7...

sougoliu的专栏 1375

IDEAL葵花宝典:java代码开发规范插件 p3c

前言:   P3C插件是阿里巴巴p3c项目组进行研发。这个项目组是阿里巴巴开发爱好者自发组织形成的虚拟项目组,根据《阿里巴巴Java开发规范》转化而成的自动化插件,并且实现了部分自动编程。 插件使用简易教程(基于IDEA): 1):打开 Settings---->Plugins---> 进行搜索--->选择---->"Alibaba Java Cod...

andymmm0925的博客 234

阿里巴巴Java开发规范终极指南:10个技巧快速提升代码质量

阿里巴巴Java开发规范(Alibaba Java Coding Guidelines)是一套由阿里巴巴集团推出的Java代码规范体系,旨在帮助开发者编写高质量、易维护的代码。本指南将通过10个实用技巧,结合p3c项目提供的IDE插件工具,帮助你快速掌握规范要点并应用到实际开发中,显著提升代码质量与团队协作效率。 ## 一、规范入门:为什么它如此重要? 在大型团队协作中,统一的代码规范是提升开

gitblog_00947的博客 1114
上一篇: Java程序猿面试分享
下一篇: SpringBoot配置MessageConvert,取消字段首字母大写自动转小写
wenyixicodedog
博客等级 码龄8年 87粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值