よく使われるjava開発テクニックのまとめ

10398 ワード

よく使われる規範テクニックのまとめ
1.クラスのネーミングには、UserServiceなどのアルパカネーミングの仕様が使用されますが、DO/BO/PO/DTO/VOという例外があります.例えば、UserPO、StudentPO(PO、VO、DTOなどの名詞は全大文字でなければならない)
@Data
@Builder
public class CustomBodyDTO {

    private String name;

    private String idCode;

    private String status;
}

2.モジュールやインタフェース、クラス、メソッドにデザインモードが使用されている場合は、名前を付けるときに体現してください.例えば、TokenFactory、LoginProxyなどです.
public class TokenFactory {


    public TokenDTO buildToken(LoginInfo loginInfo) {
        String token = UUID.randomUUID().toString();
        TokenDTO tokenDTO = TokenDTO.builder()
                .token(token)
                .createTime(LocalDateTime.now())
                .build();
        String redisKey = RedisKeyBuilder.buildTokenKey(token);
        redisService.setObject(redisKey, loginInfo, Timeout.ONE_DAY * 30 * 2);
        log.info("  token  |loginInfo={}", loginInfo.toString());
        return tokenDTO;
    }
}

3.Objectのequalsメソッドはポインタ異常を空にしやすい.ソースコードから解析equalsメソッドはObjectクラスに属しており,呼び出し元がnullであれば,自然と実行時に空のポインタが異常になる場合がある.objectクラスのソース:
    public boolean equals(Object obj) {
        return (this == obj);
    }

このような現況を避けるために、比較の際に定数または確定値のあるオブジェクトをできるだけ前に置く.
たとえば、次のようになります.
  :“test”.equals(object);
  :object.equals(“test”);

4.同じタイプのすべてのパッケージクラスを比較する場合は、equalで操作します.Integerクラスの場合、対応する変数の数値範囲が-128から127の間にある場合、そのオブジェクトはIntegerCache.cacheに格納されるため、オブジェクトが多重化される場合があるので、パッケージクラスを比較する場合はequalメソッドを統一して使用することが望ましい.
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

  public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }


5.すべてのpojoクラスの属性は、パッケージクラスの属性タイプデータを統一的に使用することが望ましい.RPCメソッドの戻り値とパラメータは、パッケージクラスデータを統一的に使用します.ローカル変数では、基本的なデータ型が使用されます.実際の応用シーンでは、例えば1つの学生クラスで、私たちが中の成績フィールドをintタイプに設定したとき、学生が試験がなければ、この成績フィールドは空であるべきだが、intのデフォルトでは0が付与されているので、このときに基本データタイプを使うと誤区が発生しやすく、0点を取ったのか、それとも試験を受けていないのか.パッケージクラスIntegerタイプを使うとnull値で区別できます.
6.pojoクラスが記述されている場合、対応するtoStringメソッドを書き換えます.pojoに別のpojoクラスが継承されている場合は、対応するtostring関数にsuper.toString()メソッドを追加します.TOStringメソッドを書き換えることで、ログ出力時に対応するオブジェクトの属性内容を逐一分析するのに役立ち、継承関係のあるオブジェクトの中にはsuper.toStringメソッドが追加され、そのオブジェクトの理解と分析に役立ちます.
7.pojoのgetterとsetterメソッドでは、ビジネスロジックのコード作成を増やさないでください.これにより、問題の調査の難易度が増加します.
    :
public class User {
    private Integer id;
    
    private String username;

    public Integer getId() {
        return id;
    }

    public User setId(Integer id) {
        this.id = id;
        return this;
    }

    public String getUsername() {
        return username;
    }

    public User setUsername(String username) {
        this.username = username;
        return this;
    }
}

    :
public class User {
    private Integer id;

    private String username;

    public Integer getId() {
        return id;
    }

    public User setId(Integer id) {
        this.id = id;
        return this;
    }

    public String getUsername() {
        return "key-prefix-"+username;
    }

    public User setUsername(String username) {
        this.username = "key-prefix-"+username;
        return this;
    }
}


8.finalは、クラス、メンバー変数、メソッド、およびローカル変数を宣言できます.finalキーを使用します.1)継承されたクラス、たとえばStringクラスは許可されません.2)POJOクラスのドメイン変数など、参照されるドメインオブジェクトの変更は許可されません.3)POJOクラスのsetterメソッドのような書き換えは許されない.4)実行中に値を再割り当てできないローカル変数.5)コンテキストが1つの変数を繰り返し使用することを回避し、final記述を使用すると、1つの変数を強制的に再定義することができ、より容易に再構築することができる.
9.どのクラスでもequalsを書き換える限りhashcodeを書き換える必要があります.例:1)HashSetは,データを格納する際に重複しないオブジェクトを格納しており,これらのオブジェクトは判断を行う際にhashcodeやequalsメソッドに依存する必要があるため書き換えが必要である.2)カスタムオブジェクトをキーキーとして使用する場合、hashcodeメソッドとequalsメソッドを書き換える必要があります.たとえば、Stringクラスはキーとして使用するのに適しています.
10.foreachサイクルで要素のremove/add操作を行わないでください.remove要素はIterator方式を使用し、同時に操作する場合はIteratorオブジェクトにロックをかける必要があります.
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (       ) {
iterator.remove();
}
}

11.HashMapを使用する場合、集合の初期化サイズを指定できます.例えば、HashMapには10000個の要素を格納する必要がありますが、初期化サイズ操作が行われていないため、要素を追加する際にhashmapの内部で拡張操作が行われ続け、性能に影響します.では、拡張動作を低減するために、初期化時にhashmapのサイズを、記憶する必要があるサイズ/負荷係数(0.75)+1に設定することができる.
   HashMap hashMap=new HashMap<>(13334);

12.Mapクラスセットにおいて、nullタイプに対してK/Vが格納されている場合:
コレクション名
key
value
説明
HashMap
nullの許可
nullの許可
スレッドが安全でない
TreeMap
nullは許可されていません
nullの許可
スレッドが安全でない
HashTable
nullは許可されていません
nullは許可されていません
スレッドのセキュリティ
ConcurrentHashMap
nullは許可されていません
nullは許可されていません
スレッドのセキュリティ
13.Set要素の唯一の特性を利用することができ、リストのcontainsメソッドを使用して遍歴、比較、再操作を避けるために、1つの集合を迅速に再操作することができる.通関観察によると,HashSet下位層は,入力された値を1つのHashMapに再入力することで操作を行い,HashMapに入った後,そのオブジェクトのhashcodeを呼び出すことで重複する値があるか否かを判断し,equals判定があれば同じ要素がなければ処理を挿入する.
   public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

14.スレッドプールはExecutorsを使用して作成することを許可しないで、ThreadPoolExecutorの方式を通じて、このような処理方式は書く学生にスレッドプールの運行規則をもっと明確にさせて、資源が消耗するリスクを回避させる.誤った方法:
      ExecutorService executors = Executors.newSingleThreadExecutor();
      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

スレッドプールのパラメータについて深く理解した上で,実際のマシンパラメータと組み合わせてパラメータ設定を行い,使用中に異常が発生することを防止する.
    ExecutorService fixedExecutorService = new ThreadPoolExecutor(
                1,
                2, 
                60,
                TimeUnit.SECONDS,
                 linkedBlockingQueue, 
                new MyThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

ps:Executors.new方式でスレッドプールを作成する欠点:*FixedThreadPoolとSingleThreadPoolの場合
許可されたリクエストキュー長はInteger.MAX_VALUEでは、大量のリクエストが蓄積され、OOMが発生する可能性があります.
CachedThreadPoolとScheduledThreadPoolの場合
許可される作成スレッド数はInteger.MAX_VALUEでは、大量のスレッドが作成され、OOMが発生する可能性があります.
15.いくつかの日付クラスを使用する場合は、Calendarクラスの代わりにLocalDateTimeを使用するか、Dateクラスの代わりにInstantを使用することをお勧めします.
16.forループ内でtry-catch操作を実行することをできるだけ避け、try-catch操作をループ体の外部に置いて使用することを選択することができる.
     :
        try {
            for (int i = 0; i < 100; i++) {
                doSomeThing();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

     :
       for (int i = 0; i < 100; i++) {
            try {
                doSomeThing();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

17.大きなセグメントのコードに対してtry-catch操作を行う.これは無責任な行為であり、安定したコードもtry-catch文ブロックの中でコードの安定性の範囲をよく区別できなかった.通常、実行中にエラーが発生しないコードブロックを安定性コードと呼び、異常なエラーが発生する可能性がある部分を非安定性コードブロックと呼び、try-catchが注目すべきオブジェクトである.
18.jdk 7の後、ストリームのような接続を閉じてリソースを解放する必要があるオブジェクトに対して、try-with-resource処理メカニズムを使用して対応することができる.たとえば、次のコードがあります.
  File file = new File("*****");
        try (FileInputStream fin = new FileInputStream(file)) {
            //      
        } catch (Exception e) {
            //      
        }

19.ArrayListを使用する場合、その指定サイズが分かれば、arraylistが新しい要素を追加し続けるにつれてチェーンテーブルの体積が拡大するため、できるだけ初期化時にサイズ指定を行うことができます.
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

20.メール、メール、電話、注文、支払いなどのアプリケーションシーンでは、開発時に重複防止機能の制限を設定し、悪意のあるブラシが発生しないようにする必要があります.
21.敏感な語彙の発表には、テキストフィルタリングの戦略を考慮する必要があります.この機能は、市販の成熟したUGC監視サービスに直接アクセスしたり、社内で独自に開発したugcフィルタリングツールを使用したりして、ユーザーが悪意のあるコメントを発表しないようにするなどの状況を考慮することができます.
22.インデックスを作成する際、インデックスの命名には一定の規範に従う必要があります.
索引タイプ
命名規則
ケース
プライマリ・キー索引
pk_フィールド名、pkはprimary keyを指します
pk_order_id
ユニークインデックス
uk_フィールド名、ukはunique keyを指す
uk_order_id
一般索引
idx_フィールド名、idxはindexを指します
idx_order_id
23.テキスト情報を格納する必要がある場合は、まず格納テキストの長さを考慮する必要があり、テキストの長さが5000を超える場合はvarcharタイプで格納することを推奨せず、textタイプでデータ格納することを考慮することができ、この場合は1枚のテーブルでデータを格納し、追加のプライマリキーidで対応することを考慮することができる.これにより、他のフィールドに影響を及ぼすクエリーが回避されます.
24.データベースの命名を行うときは、できるだけデータベースの名前とプロジェクトプロジェクトの名前が一致することを保証します.
25.テーブル構造の設計を行う場合、一意の性質を持つフィールドが一意のインデックスを確立する必要がある限り、後期にクエリーを行う際にクエリーの効率を高めるのに役立ち、一意のインデックスという層の保障がなく、ビジネス層にブロックが加わっても、オンラインの汚れたデータの発生を招きやすい.
26.order byのようなsqlクエリーを行う場合は、クエリーインデックスの秩序性に注意する必要があります.インデックスの構築については、三星インデックスなどのインデックスの星評価を理解することができます.しかし、個人的にはインデックスには最適性というものはなく、実際のビジネスシーンと結びつけて設計する必要があると考えています.
21.MySQLでは、count(*)を使用するとNULLの値を持つローが統計され、count(カラム名)はNULLの値を持つローは統計されません.
22.データベースストレージエンジンの選択を行う場合は、関連するアプリケーションシーンと組み合わせて選択する必要があり、select操作が多い場合はMyIsamストレージエンジン、データに対するinsert,updateのような修正操作が多いビジネスシーンを適用する必要がある場合はinnodbストレージエンジンを優先的に推奨する.現在、一般的なインターネット会社ではinnodbの使用が推奨されています.