Featured image of post 【合集】Java编码规范

【合集】Java编码规范

兵无常势,水无常形。

阿里Java开发手册(黄山版).pdf

阿里Java开发手册(黄山版).pdf

where 1=1

SQL优化器优化后走索引,但是优化需要时间,使用标签替代

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 <!--反例-->
<select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">
    select count(*) from t_rule_BookInfo t
    where 1=1
    <if test="title !=null and title !='' ">
        AND title = #{title}
    </if>
    <if test="author !=null and author !='' ">
        AND author = #{author}
    </if>
</select>

<!--正例-->
<select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">
select count(*) from t_rule_BookInfo t
<where>
    <if test="title !=null and title !='' ">
        title = #{title}
    </if>
    <if test="author !=null and author !='' ">
        AND author = #{author}
    </if>
</where>
</select>

迭代entrySet() 获取Map 的key 和value

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Map 获取value 反例:
HashMap<String, String> map = new HashMap<>();
for(
    String key :map.
    keySet()){
    String value = map.get(key);
}

// Map 获取key & value 正例:
for(
    Map.Entry<String, String> entry :map.
    entrySet()){
    String key = entry.getKey();
    String value = entry.getValue();
}

使用Collection.isEmpty() 检测空

Collection.size() 方法实现的时间复杂度可能是O(n)

任何Collection.isEmpty() 实现的时间复杂度都是O(1)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 反例
LinkedList<Object> collection = new LinkedList<>();
if(collection.size() ==0){
    System.out.
    println("collection is empty.");
}

// 正例
if(collection.isEmpty()){
    System.out.
    println("collection is empty.");
}

// 检测是否为null 可以使用CollectionUtils.isEmpty()
if(CollectionUtils.isEmpty(collection)){
    System.out.
    println("collection is null.");
}

初始化集合时尽量指定其大小

1
2
3
4
尽量在初始化时指定集合的大小能有效减少集合的扩容次数
因为集合每次扩容的时间复杂度很可能时O(n)耗费时间和性能
int[] arr2 = new int[]{1, 2, 3, 4};
List<Integer> list2 = new ArrayList<>(arr2.length);

使用StringBuilder 拼接字符串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 一般的字符串拼接在编译期Java 会对其进行优化,但是在循环中字符串的拼接Java 编译期无法执行优化,
// 所以需要使用StringBuilder 进行替换。
// 反例:
String str = "";
for(int i = 0; i< 10;i++){
    //在循环中字符串拼接Java 不会对其进行优化
    str +=i;
}

// 正例:
String str1 = "Love";
String str2 = "Courage";
//Java 编译器会对该普通模式的字符串拼接进行优化
String strConcat = str1 + str2;
StringBuilder sb = new StringBuilder();
for(int i = 0; i< 10;i++){
    //在循环中,Java 编译器无法进行优化,所以要手动使用StringBuilder
    sb.append(i);
}

若需频繁调用Collection.contains 方法则使用Set

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 若代码中需要频繁调用contains 方法查找数据则先将集合list 转换成HashSet 实现,将O(n) 的时间复杂度将为O(1)。
// 在Java 集合类库中,List的contains 方法普遍时间复杂度为O(n),

// 反例:
//频繁调用Collection.contains() 反例
List<Object> list = new ArrayList<>();
for(int i = 0; i <=Integer.MAX_VALUE;i++){
    //时间复杂度为O(n)
    if(list.contains(i)){
        System.out.
        println("list contains "+i);
     }
 }

// 正例:
//频繁调用Collection.contains() 正例
List<Object> list1 = new ArrayList<>();
Set<Object> set = new HashSet<>(list1);
for(int i = 0; i <=Integer.MAX_VALUE;i++){
    //时间复杂度为O(1)
    if(set.contains(i)){
        System.out.println("list contains "+i);
    }
}

使用静态代码块实现赋值静态成员变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 对于集合类型的静态成员变量,应该使用静态代码块赋值,而不是使用集合实现来赋值。

// 赋值静态成员变量反例
Map<String, Integer> map = new HashMap<String, Integer>() {
    {
        map.put("Leo", 1);
        map.put("Family-loving", 2);
        map.put("Cold on the out side passionate on the inside", 3);
    }
};

List<String> list = new ArrayList<>() {
    {
        list.add("Sagittarius");
        list.add("Charming");
        list.add("Perfectionist");
    }
};

//赋值静态成员变量正例
Map<String, Integer> map = new HashMap<String, Integer>();

static {
    map.put("Leo", 1);
    map.put("Family-loving", 2);
    map.put("Cold on the out side passionate on the inside", 3);
}

List<String> list = new ArrayList<>();

static {
    list.add("Sagittarius");
    list.add("Charming");
    list.add("Perfectionist");
}

删除未使用的局部变量、方法参数、私有方法、字段和多余的括号。

工具类中屏蔽构造函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 工具类是一堆静态字段和函数的集合,其不应该被实例化;
// 但是,Java 为每个没有明确定义构造函数的类添加了一个隐式公有构造函数,
// 为了避免不必要的实例化,应该显式定义私有构造函数来屏蔽这个隐式公有构造函数。

// 工具类构造函数反例
class PasswordUtils {
}

// 工具类构造函数正例
class PasswordUtils2 {
    //定义私有构造函数来屏蔽这个隐式公有构造函数
    private PasswordUtils2() {
    }
}

删除多余的异常捕获并抛出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 用catch 语句捕获异常后,若什么也不进行处理,就只是让异常重新抛出,这跟不捕获异常的效果一样,可以删除这块代码或添加别的处理。

// 多余异常反例
try(BufferedReader reader = new BufferedReader(new FileReader(fileName))){
    String line;
    StringBuilder builder = new StringBuilder();
   while((line =reader.readLine())!=null){
        builder.append(line);
   }
   return builder.toString();
}catch(Exception e){
    //仅仅是重复抛异常 未作任何处理
    throw e;
}

// 多余异常正例
try(
    BufferedReader reader = new BufferedReader(new FileReader(fileName))){
    String line;
    StringBuilder builder = new StringBuilder();
    while((line =reader.readLine())!=null){
        builder.append(line);
    }
    return builder.toString();
    //删除多余的抛异常,或增加其他处理:
    /*catch (Exception e) {
         return "fileReader exception";
    }*/
}

字符串转化使用String.valueOf(value) 代替 " " + value

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 把其它对象或类型转化为字符串时,使用String.valueOf(value) 比 ""+value 的效率更高。
//把其它对象或类型转化为字符串反例:
int num = 520;
// "" + value
String strLove = "" + num;

//把其它对象或类型转化为字符串正例:
// String.valueOf() 效率更高
strLove =String.
valueOf(num);

BigDecimal.valueOf() 代替 new BigDecimal(double)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// BigDecimal(double) 存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。
BigDecimal bigDecimal = new BigDecimal(0.11D); // 反例
BigDecimal bigDecimal1 = BigDecimal.valueOf(0.11D); // 正例
System.out.
println(bigDecimal);  // 0.11000000000000000055511151231257827021181583404541015625
System.out.
println(bigDecimal1); // 0.11

BigDecimal bigDecimal2 = new BigDecimal("0.11"); // 也可以
System.out.
println(bigDecimal2); // 0.11

返回空数组和集合而非 null

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 若程序运行返回null,需要调用方强制检测null,否则就会抛出空指针异常;
// 返回空数组或空集合,有效地避免了调用方因为未检测null 而抛出空指针异常的情况,还可以删除调用方检测null 的语句使代码更简洁。

// 返回null 反例
public static Result[] getResults() {
    return null;
}

public static List<Result> getResultList() {
    return null;
}

public static Map<String, Result> getResultMap() {
    return null;
}

// 返回空数组和空集正例
public static Result[] getResults() {
    return new Result[0];
}

public static List<Result> getResultList() {
    return Collections.emptyList();
}

public static Map<String, Result> getResultMap() {
    return Collections.emptyMap();
}

常量.equals 或者 Objects.equals

1
2
3
4
5
String fileName = "resources/file.txt";
"Charming".
equals(fileName);
Objects.
equals("Charming",fileName);

枚举的属性字段必须是私有且不可变

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改;
// 理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的Setter 方法,最好加上final 修饰符。

// 正例: SwitchStatus
SwitchStatus enabled = SwitchStatus.ENABLED;

public enum SwitchStatus {
    // 枚举的属性字段正例
    DISABLED(0, "禁用"),
    ENABLED(1, "启用");

    // 私有 final 修饰
    private final int value;
    private final String description;

    // 私有
    private SwitchStatus(int value, String description) {
        this.value = value;
        this.description = description;
    }

    // 没有Setter 方法
    public int getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }
}

String.split(String regex)部分关键字需要转译

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 使用字符串String 的plit 方法时,传入的分隔字符串是正则表达式,则部分关键字(比如 .| 等)需要转义。
// String.split(String regex) 反例
String[] split = "a.ab.abc".split(".");
System.out.
println(Arrays.toString(split));   // 结果为[]
String[] split1 = "a|ab|abc".split("|");
System.out.
println(Arrays.toString(split1));  // 结果为["a", "|", "a", "b", "|", "a", "b", "c"]

// String.split(String regex) 正例
// . 需要转译
String[] split2 = "a.ab.abc".split("\\.");
System.out.
println(Arrays.toString(split2));  // 结果为["a", "ab", "abc"]

// | 需要转译
String[] split3 = "a|ab|abc".split("\\|");
System.out.
println(Arrays.toString(split3));  // 结果为["a", "ab", "abc"]
Licensed under CC BY-NC-SA 4.0
皖ICP备2024056275号-1
发表了78篇文章 · 总计148.99k字
本站已稳定运行