java - コーディングについて考える

nullを使わない
----------------

  一部のツールを除いてロジック内ではnullを返さないようにする。 
  また、nullチェックは、データを手に入れた直後にだけ行うこと。Listであれば空のリストにすればif文が一つ減る。

  ×
  
```java:
    List<User> myList = myServce.getList();
    if (myList != null) {
      for (User user : myList) {
        ....
      }
    }
```
  ◯
  
```java:
    List<User> myList = myServce.getList();
    for (User user : myList) {
      ....
    }
```
変数を書き換えない
--------------------

  無意味な代入をしない。変数の書き換えはできる限り避け、新しい変数を利用する。
  そうすることで、同じ値が入っていることが期待されるため、バグが生まれにくく、 変数の宣言場所を見れば何が変数に入っているかがすぐにわかるようになり、読みやすくなる。

  ×
  
```java:
    List myList = new ArrayList();
    if (user.exist()) {
      myList = getA();
    } else {
      myList = getB();
    }
```
空のブロックを作らない
-----------------------

  処理の書き忘れなのか、意図的なものなのかがわからないため。 コメントに、「理由」を明確に書く。
  
例外処理を正しく行う
---------------------

  下のソースコードには三つの間違いがあります。

  ×
  
```java:
    try {
      ....
    } catch (IllegalAccessException e) {
      e.printStackTrace();
      throw new RuntimeException();
    }
```
  1. printStackTraceを使わない。 System.out.printも同様に不可です。 Logを必ず使用してください。 出力レベルや出力先を選べないSystem.outやprintStackTraceは製品につけるものではありません。
  2. RuntimeExceptionは使わない。 基底クラスであるRuntimeExceptionは使用してはいけません。 かならず、状況に合わせたサブクラスを作って投げてください。
  3. Exceptionのコンストラクタ引数 上の例であれば例外をラップして投げなおすために、

```java:
      throw new SubClassException?(e);
```

として、引数に原因となった例外をつける必要があります。 また、メッセージを付加するのも有用となるケースが多いです。

```java:
      throw new SubClassException?("Dao生成失敗", e);
```

ただし、例外のラップではなく、自分が初めてthrowする場合は、メッセージは必須です。 たとえば、データがすでに存在しているため、Exceptionを発生させるときは、


```java:
      throw new RecordAlreadyExistsException?("社員ID:" + n + "はすでに存在しています。");
```
となります。

拡張for文を使用する
----------------------

  ×
  
```java:
    for (int i = 0; i < users.length; i++) {
      User user = users.get(i);
      ....
    }
```
  ◯
  
```java:
    for (User user : users) {
      ....
    }
```
new Integerを使わない
---------------------------

  new Integer や new Long などのプリミティブラッパークラスを絶対に new しない Intger.valueOfやLong.valueOfを使うこと。 あるいは 1 や 1l と書けば必要なときに変換してくれるのでそちらを使う。
  ただし、BigIntegerやBigDecimalでStringから変換するときは使用することを薦める。
  
List.removeを使わない
---------------------------

  以下のコードでは、まったく意図したように動きません。 List.removeを使うとforでまわしている配列の状態が変わってしまうため、 全件を操作することができません。
  Iterator.removeはループ中に削除することを念頭に設計されているため、問題なく動きます。 また、削除でなく、新規リストを一つ作り、条件に合致しないもののみを追加するのがもっとも簡単な方法です。

  ×
  
```java:
    List<Integer> first = new ArrayList<Integer>(Arrays.asList(1, 1, 2, 3, 1));
    List<Integer> second = new ArrayList<Integer>(Arrays.asList(1, 2));
    for (int i = 0; i < first.size(); ++i) {
      Integer f = first.get(i);
      for (int j = 0; j < second.size(); ++j) {
        if (f.equals(second.get(j))) {
          first.remove(i);
        }
      }
    }
```

配列定数使用時の注意点
-------------------------

  配列の定数は変更ができてしまうので、 変更不可にする必要があります。
  
  ×
  
```java:
    public class FinalArrayTest {
      //定数
      static final String[] TEST_ARRAY = {"AAA","BBB"};
      /** Main Method */
      public static void main(String[] args) {
        System.out.println(TEST_ARRAY[0]);
        TEST_ARRAY[0] = "XXX";
        System.out.println(TEST_ARRAY[0]);
      }
    }
```
  実行結果::
  
    AAA
    XXX
    
  ◯
  
```java:
    public class FinalArrayTest {
      //定数
      public static final List<String> TEST_ARRAY = Collections.unmodifiableList(Arrays.asList(new String[]{"AAA","BBB"}));
      /** Main Method */
      public static void main(String[] args) {
        System.out.println(TEST_ARRAY.get(0));
        try{
           //追加してみる。
          TEST_ARRAY.add("XXX");
        }catch (UnsupportedOperationException e) {
          System.out.println("1# : " + e);
         }
        try{
           //削除してみる。
          TEST_ARRAY.remove(0);
        }catch (UnsupportedOperationException e) {
          System.out.println("2# : " + e);
        }
      }
    }
```
  実行結果::
  
    AAA
    1# : java.lang.UnsupportedOperationException
    2# : java.lang.UnsupportedOperationException