【開発スキル】コーディング基準とは(1)

背景:Javaコードをより標準化された方法で作成する方法の重要性は、言わないでください。最も重要なポイントは、コードのパフォーマンスを向上させ、コードをバグから遠ざけ、コードをよりエレガントにすることです。

目次

1.MyBatisは複数のクエリ条件に対して1 = 1を書き込みません

2. entrySet()を繰り返して、マップのキーと値を取得します

3. Collection.isEmpty()を使用して空を検出します

4.コレクションを初期化するときにそのサイズを指定してみてください

5.StringBuilderを使用して文字列を連結します

6. Collection.containsメソッドを頻繁に呼び出す必要がある場合は、Setを使用します

7.静的コードブロックを使用して、静的メンバー変数の割り当てを実現します

8.未使用のローカル変数、メソッドパラメータ、プライベートメソッド、フィールド、および余分な括弧を削除します。

9.ツールクラスのシールドコンストラクタ

10.冗長な例外キャッチアンドスローを削除します

11.文字列変換では、 "" + valueの代わりにString.valueOf(value)を使用します

12. BigDecimal(double)の使用は避けてください

 13.nullの代わりに空の配列とコレクションを返す

14.equalsメソッドを呼び出すために定数または特定の値を使用することをお勧めします

15.列挙された属性フィールドは、プライベートで不変である必要があります

16. tring.split(String regex)いくつかのキーワードを翻訳する必要があります


1.  MyBatisのは、複数のクエリ条件を1 = 1を書きません

複数のクエリ条件が発生した場合、where 1 = 1を使用すると問題を簡単に解決できますが、「where 1 = 1」のフィルター条件を追加すると、データベースシステムが不可能になるため、パフォーマンスが大幅に低下する可能性があります。インデックスなどのクエリ最適化戦略を使用します。データベースシステムは、データの各行をスキャンして(つまり、テーブル全体のスキャン)、行がフィルター条件を満たしているかどうかを比較するように強制されます。テーブル内のデータ量が多い場合、クエリ速度非常に遅くなります;さらに、SQLインジェクションのリスクがあります。

  • 反例
    <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>

UPDATE操作についても同じことが言えます。1= 1の代わりにフラグを使用できます。

2.  entrySet()を繰り返して、マップのキーと値を取得します

マップの主キーキーのみがループで必要な場合、keySet()の反復は正しいですが、主キーキーと値の値が必要な場合、entrySet()の反復は、keySet()の反復よりも効率的です。後でgetを介して値を取得することをお勧めします。

反例:

//Map 获取value 反例:
HashMap<String, String> map = new HashMap<>();
for (String key : map.keySet()){
    String value = map.get(key);
}

正例:

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

3.  Collection.isEmpty()を使用して空を検出します

Collection.size()を使用して空かどうかを検出することは論理的に問題ありませんが、Collection.isEmpty()を使用すると、コードが読みやすくなり、パフォーマンスが向上します。さらに、Collection.isEmpty()の実装時間計算量はOです。 (1)、複数回トラバースする必要はありませんが、Collection.size()メソッドによって達成される時間計算量の一部はO(n)である可能性があります。

反例:

LinkedList<Object> collection = new LinkedList<>();
if (collection.size() == 0){
 System.out.println("collection is empty.");
}

正例:

LinkedList<Object> collection = new LinkedList<>();
if (collection.isEmpty()){
    System.out.println("collection is empty.");
}
 
//检测是否为null 可以使用CollectionUtils.isEmpty()
if (CollectionUtils.isEmpty(collection)){
    System.out.println("collection is null.");
 
}

4. コレクションを初期化するときにそのサイズを指定してみてください

コレクションの各拡張の時間計算量はO(n)である可能性が高く、時間とパフォーマンスを消費するため、初期化中にコレクションのサイズを指定してください。これにより、コレクションの拡張数を効果的に減らすことができます。

反例:

//初始化list,往list 中添加元素反例:
int[] arr = new int[]{1,2,3,4};
List<Integer> list = new ArrayList<>();
for (int i : arr){
 list.add(i);
}

正例:

//初始化list,往list 中添加元素正例:
int[] arr = new int[]{1,2,3,4};
//指定集合list 的容量大小
List<Integer> list = new ArrayList<>(arr.length);
for (int i : arr){
    list.add(i);
}

5. スプライス文字列への使用のStringBuilder

一般的な文字列スプライシングはコンパイル時にJavaによって最適化されますが、ループ内の文字列スプライシングはJavaコンパイル時に最適化できないため、置換にはStringBuilderを使用する必要があります。

反例:

//在循环中拼接字符串反例
String str = "";
for (int i = 0; i < 10; i++){
    //在循环中字符串拼接Java 不会对其进行优化
    str += i;
}

正例:

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

6.  Collection.containsメソッドを頻繁に呼び出す必要がある場合は、Setを使用します

Javaコレクションクラスライブラリでは、Listのcontainsメソッドの一般的な時間計算量はO(n)です。データを検索するためにcontainsメソッドをコードで頻繁に呼び出す必要がある場合は、最初にコレクションリストをHashSet実装に変換します。 O(n)の時間計算量はO(1)になります。

反例:

//频繁调用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> list = new ArrayList<>();
Set<Object> set = new HashSet<>();
for (int i = 0; i <= Integer.MAX_VALUE; i++){
    //时间复杂度为O(1)
    if (set.contains(i)){
        System.out.println("list contains "+ i);
    }
}

7. 静的コードブロックを使用して、静的メンバー変数の割り当てを実現します

コレクションタイプの静的メンバー変数の場合、コレクションの実装を使用して値を割り当てる代わりに、静的コードブロックの割り当てを使用する必要があります。

反例:

//赋值静态成员变量反例
private static 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);
    }
};
private static List<String> list = new ArrayList<>(){
    {
        list.add("Sagittarius");
        list.add("Charming");
        list.add("Perfectionist");
    }
};

正例:

//赋值静态成员变量正例
private static 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);
}
 
private static List<String> list = new ArrayList<>();
static {
    list.add("Sagittarius");
    list.add("Charming");
    list.add("Perfectionist");
}

8. 未使用のローカル変数、メソッドパラメータ、プライベートメソッド、フィールド、および余分な括弧を削除します。

9. ツールクラスのシールドコンストラクター

ユーティリティクラスは静的フィールドと関数のコレクションであり、インスタンス化しないでください。ただし、Javaは、明確に定義されたコンストラクタを持たないクラスごとに暗黙のパブリックコンストラクタを追加します。不要なインスタンス化を回避するには、明示的に定義する必要があります。この暗黙のパブリックコンストラクターをシールドするプライベートコンストラクター。

反例:

public class PasswordUtils {
//工具类构造函数反例
private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);
 
public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";
 
public static String encryptPassword(String aPassword) throws IOException {
    return new PasswordUtils(aPassword).encrypt();
}

正例:

public class PasswordUtils {
//工具类构造函数正例
private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);
 
//定义私有构造函数来屏蔽这个隐式公有构造函数
private PasswordUtils(){}
 
public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";
 
public static String encryptPassword(String aPassword) throws IOException {
    return new PasswordUtils(aPassword).encrypt();
}

10. 冗長な例外キャプチャを削除してスローします

catchステートメントで例外をキャッチした後、何も処理されない場合は、例外を再スローします。これは、例外をキャッチしないのと同じです。このコードを削除するか、他の処理を追加できます。

反例:

//多余异常反例
private static String fileReader(String fileName)throws IOException{
 
    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;
    }
}

正例:

//多余异常正例
private static String fileReader(String fileName)throws IOException{
 
    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";
        }*/
    }
}

11. 文字列変換では、 "" + valueの代わりにString.valueOf(value)を使用します

他のオブジェクトまたはタイプを文字列に変換する場合、String.valueOf(value)を使用する方が "" + valueよりも効率的です。

反例:

//把其它对象或类型转化为字符串反例:
int num = 520;
// "" + value
String strLove = "" + num;

正例:

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

12.  BigDecimal(double)の使用は避けてください

BigDecimal(double)は精度を失うリスクがあり、正確な計算または値の比較のシナリオでビジネスロジックの異常を引き起こす可能性があります。

反例:

// BigDecimal 反例    
BigDecimal bigDecimal = new BigDecimal(0.11D);

正例:

// BigDecimal 正例
BigDecimal bigDecimal1 = bigDecimal.valueOf(0.11D);

 13.nullの 代わりに空の配列とコレクションを返す

プログラムがnullを返す場合、呼び出し元はnullを検出するように強制する必要があります。そうしないと、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();
}

14. 最初に定数または特定の値を使用してequalsメソッドを呼び出します

オブジェクトのequalsメソッドは、nullポインタ例外を簡単にスローします。equalsメソッドを呼び出すには、定数または特定の値を持つオブジェクトを使用する必要があります。

反例:

//调用 equals 方法反例
private static boolean fileReader(String fileName)throws IOException{
 
 // 可能抛空指针异常
 return fileName.equals("Charming");
}

正例:

//调用 equals 方法正例
private static boolean fileReader(String fileName)throws IOException{
 
    // 使用常量或确定有值的对象来调用 equals 方法
    return "Charming".equals(fileName);
 
    //或使用:java.util.Objects.equals() 方法
   return Objects.equals("Charming",fileName);
}

15. 列挙された属性フィールドは、プライベートで不変である必要があります

列挙型は通常、定数として使用されます。列挙型にパブリック属性フィールドまたは設定フィールドメソッドがある場合、これらの列挙型定数の属性は簡単に変更できます。理想的には、列挙型の属性フィールドはプライベートであり、プライベート割り当てではコンストラクター、対応するSetterメソッドはありません。最後の修飾子を追加するのが最善です。

反例:

public enum SwitchStatus {
    // 枚举的属性字段反例
    DISABLED(0, "禁用"),
    ENABLED(1, "启用");
 
    public int value;
    private String description;
 
    private SwitchStatus(int value, String description) {
        this.value = value;
        this.description = description;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
}

正例:

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;
    }
}

16.  tring.split(String regex)いくつかのキーワードを翻訳する必要があります

Stringのsplitメソッドを使用する場合、入力区切り文字列は正規表現であり、一部のキーワード(。[]()|など)はエスケープする必要があります。

反例:

// 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"]

 

おすすめ

転載: blog.csdn.net/qq_41893274/article/details/113525352