新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

Java技法まとめ

[Java]Java技法まとめ

色々技法を学んだのに忘れがちなので、まとめておく

内容

if文の短縮
if (str != null && str.equals("hoge")) { ... }
<||
- 左側のstr != nullが評価され、falseなら右の式は評価されないため、NullPointerExceptionは発生しない
- Stringの場合は"hoge".equals(str)にした方が安全だが…

*** コンストラクタの連結
>|java|
public Hoge() {
    this("NO NAME");
}

public Hoge(String name) {
    this.name = name;
}
...
    { this(buildClassText()); }
...
static String buildClassText() { ... }
アクセス制限について
  • 属性はprivate, インタフェースメソッドはpublic, ヘルパメソッドはprotected
    • ヘルパをprotectedにするのは、クラスを拡張したときに、一部メソッドを変更できるので
public class Hoge {
    private int value;
    public setValue(int value) { this.value = value; }
    public void someMethod(Hoge obj) {
        // 適当な値を設定できてしまう!
        obj.value = 10000000;
    }
}
    • 基本的には直接値を設定するのはsetterのみにする
    • setterメソッドで値の検証を行う

※研修でフィールドもsetterもともにprivateな例があり、何に使うのかわからなかったが、あれは
1) クラス内でしか扱わないフィールドで、
2) かつsetter内で値の検証を行っており、
3) setter以外のメソッドでprivateフィールドの値を変更する可能性がある
ということかな?

System.exit
  • 使うのはmainメソッドのみにすべき
    • ライブラリなどで使用すると、アプリケーション全体を終了させてしまうので
else文やdefaultブロックで特定の処理を書かない
// int型変数numの値は0か1か2しか取らない

/* ダメな例 */
if (value == 0) { /* valueが0の場合の処理 */ }
else if (value == 1) { /* valueが1の場合の処理 */ }
else { /* valueが2の場合の処理 */ }

/* 良い例 */
if (value == 0) { /* valueが0の場合の処理 */ }
else if (value == 1) { /* valueが1の場合の処理 */ }
else if (value == 2) { /* valueが2の場合の処理 */ }
else { /* 例外を発行! */ }
finalなコレクション
public static final Set VALUD_COLORS;
static {
    Set temp = new HashSet();
    temp.add(Color.red);
    temp.add(Color.blue);
    ...
    VALID_COLORS = Collections.unmodifiableSet(temp);
}
setter/getterでは全ての可変オブジェクトをコピーする
public class SomeData {
    // 基本型, Stringなら下記で問題ない
    private final String name;
    private final int id;
    
    public void getName() { return this.name; }
    public void getId() { return this.id; }

    // しかし、オブジェクト型だと...
    private final Point value;
    public Point getValue{ return this.value; }
}

public static void main(String[] args) {
    SomeData sd = new SomeData();
    Point pos = sd.getValue();
    pos.x = 100000;    // 同じ参照を指すので、sd.valueにアクセス・値を変更できてしまう!
}
  • 上記のような問題があるので、コンストラクタ・setter・getterではオブジェクトのコピーを生成して設定or返却すべし
public class SomeData {
    private final Point value;
    public SomeData(Point value) {
        this.value = new Point(value);
    }
    public Point getValue{ 
        return new Point(this.value);
    }
    public void setValue(Point value) {
        this.value = new Point(value);
    }
}
拡張for文でのMapの使用
for (Map.Entry<String, String> entry : map.entrySet()) {
    Object key = entry.getKey();
    Object value = entry.getValue();
}
  • entrySet()でMap.EntryというインタフェースのSetが返ってくる
  • 各entryについてkeyとvalueをgetできる
既存の例外を使うべし
public void setName( final String name ) {
    if (name == null) throw new NullPointerException():
    if (name.length == 0) throw new IllegalArgumentException();
    this.name = name;
}
無名クラス
  • ボタンクリック時のアクションを定義
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("click!!!");
    }
});

*** 定数オブジェクト
public class Gender {
	public static final Gender MALE = new Gender("MALE");
	public static final Gender FEMALE = new Gender("FEMALE");

	private final String name;   
 
	private Gender(final String name) {
		this.name = name;
	}
}

public class Person {
	private Gender gender = Gender.MALE;
}
制約オブジェクト
// 制約例外クラス
public class ConstraintException extends RuntimeException {

	private ConstraintExceptionType exceptionType;

	public ConstraintException(final ConstraintExceptionType exceptionType) {
		super("specifier = " + exceptionType.getName());
		this.exceptionType = exceptionType;
	}

	public ConstraintException(final ConstraintExceptionType exceptionType,
			final String msg) {
		super(msg);
		this.exceptionType = exceptionType;

	}

	public ConstraintExceptionType getExceptionType() {
		return this.exceptionType;
	}
}

// 制約オブジェクトの基本クラス
public abstract class Constraint {
	private String name;
	
	protected Constraint(final String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}
}

// 整数の基本例外クラス
public class IntConstraint extends Constraint {
	private int minValue;
	private int maxValue;

	protected IntConstraint(final String name, final int minValue,
			final int maxValue) {
		super(name);
		this.minValue = minValue;
		this.maxValue = maxValue;
	}

	public int getMinValue() {
		return this.minValue;
	}

	public int getMaxValue() {
		return this.maxValue;
	}

	public void validate(final int value) {
		if (minValue > value) {
			throw new ConstraintException(
					ConstraintExceptionType.VALUE_BELOW_MINIMUM);
		}
		if (maxValue < value) {
			throw new ConstraintException(
					ConstraintExceptionType.VALUE_ABOVE_MAXIMUM);
		}
	}
}

// 制約オブジェクトの使用例
public class Rectangle {
	public static final IntConstraint WIDTH_CONSTRAINT = new IntConstraint(
			"Width", 0, Integer.MAX_VALUE);
	public static final IntConstraint HEIGHT_CONSTRAINT = new IntConstraint(
			"Height", 0, Integer.MAX_VALUE);
	private int width;
	private int height;

	public Rectangle(final int width, final int height) {
		WIDTH_CONSTRAINT.validate(width);
		WIDTH_CONSTRAINT.validate(height);

		this.width = width;
		this.width = height;
	}