【Effective Java】不必要なオブジェクトの生成を避ける
Effective Javaの独自解釈です。
第3版の項目6について、自分なりにコード書いたりして解釈してみました。
概要
- どこでオブジェクトが生成されるかを意識する。
- 用意されているオブジェクトの存在を知る。
- 何度も同じ値で再利用されるようなオブジェクトは定数化する。
- ボクシングでオブジェクトが意図せず作成されることに注意する。
不必要にオブジェクトが生成される例と対策
String
String s = new String("hoge");
String
String s = new String("hoge");
このコードでは、まず”hoge”
という文字が入ったオブジェクトが作成され、次にnew String(“hoge”)
で”hoge”
という文字が入った別のオブジェクトが作成される。
要するに中身が同じオブジェクトが二重に生成されるのである。以下のようにすることで、オブジェクト生成を一回で済ませられる。
String s = "hoge";
Boolean
Boolean
オブジェクトは実は以下のように、String
オブジェクトを引数にすることで生成することができる。
Boolean b = new Boolean("true");
しかしそもそもBoolean
はnull
, true
, false
の三つの値しかとらない。Boolean
クラスにはtrue
とfalse
のオブジェクトが定数の形で予め用意されている。
Booleanクラスの一部
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
また、これらの定数を返すvalueOf
メソッドも用意されている。
public static Boolean valueOf(String s) {
return parseBoolean(s) ? TRUE : FALSE;
}
ということで、以下のようにvalueOf
メソッドを利用してBoolean
オブジェクトを宣言すれば、元々Boolean
クラスで用意されているオブジェクトを参照し、あらたに生成する必要することがなくなる。
Boolean b = Boolean.valuOf("true");
メソッドが呼ばれる度に生成されるオブジェクト
以下の、文字列が正しいローマ数字であるか判定するメソッドを考える。
static boolean isRomanNumeral(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
String.matches
は、内部的にPattern
オブジェクトを生成しているので、このメソッドが呼ばれる度に新たなPattern
オブジェクトが生成されてしまう。
予めPattern
オブジェクトを定数として定義しておけば、Pattern
オブジェクト生成はクラス初期化時の一回で済ませることができる。
public class RomanNumerals {
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
}
※ String.matches
は内部的にPattern
オブジェクトを生成し、そのオブジェクトから.matcher(判定対象文字列).matches()
を呼んでいるので、Pattern
オブジェクト生成部分が丸ごと省略された形となる。
不必要なボクシング
以下のコードを考える。
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += 1;
return sum;
}
sum += 1
は内部的にLong sum = sum + (Long)1
のように毎回キャストされて演算されているので、毎回Long
オブジェクトが生成されてしまう。
そもそもこのメソッドはsum
がLong
型である必要がないため、sum
をlong
型で宣言するだけで大幅に速度改善できる。
これはわかりやすい例だが、わざわざラッパークラスを使用する必要があるかどうかは常に意識すべきである(null
を取る必要性、シチュエーションがありえるかどうかなど)。
注意
メソッドの引数のオブジェクトは、メソッド内部で状態を変更すべきではないという考えがある。今そのオブジェクトがどういう状態になっているかが見えにくく、バグ発生リスクが上がるからである。
よほどパフォーマンスが求めらていない限り、この場合はメソッド内で新たにオブジェクトを生成し、引数のオブジェクトの内容をコピーすることでバグ発生リスクの低減を優先すべきだと考える。
Author And Source
この問題について(【Effective Java】不必要なオブジェクトの生成を避ける), 我々は、より多くの情報をここで見つけました https://qiita.com/kenduck/items/f0606089f55397d92c5b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .