私は Java の初心者で、コンストラクターの使用についていくつか質問があります。
Map<String, Object> map = new HashMap<String, Object>();
map.put("one", new String("Hello"));//1
map.put("two", "world");//2
どちらのステートメントがよりひどいですか? どんな違い?どれが最高ですか?
どちらの形式も同じことを行いますが、ボンネットの下には違いがあります。コンストラクターを使用する場合String
、内部文字列プールをスキップし、常に新しいオブジェクトを作成します。一方、文字列リテラルを使用すると、最初にプール内の文字列が検索され、そこで見つかった場合は再利用されます (新しい文字列を作成する場合のみ)以前はプールにありませんでした) - したがって、不要なオブジェクトのインスタンス化を回避するため、より効率的です。ちなみに、文字列はimmutableであるため、プールから共有できます。
多くの静的コード分析ツールは、String
コンストラクターの使用を適切なプログラミング プラクティスに違反しているとフラグを立てており、一般的には回避する必要があります。
最初の1つ:
map.put("one", new String("Hello"));//1
ほとんど必要ありません。これにより、不要なString
オブジェクトが作成されます。ただし、単一のオブジェクトであるため、実行時にはそれほど重要ではありません。しかし、ループ内でこのように使用すると、間違いなく違いが生じます。ループ内でのオブジェクト作成はコストのかかる操作です。
一方、2番目のもの:
map.put("two", "world");//2
String Literal Poolからインターンされた文字列リテラルを再利用します。文字列リテラル プールは、ヒープ上に作成された文字列オブジェクトへの参照のコレクションです。Java は文字列リテラルを自動的にインターンするため、同じ文字列リテラルを複数回使用しても新しい文字列オブジェクトが毎回作成されることはありません。文字列リテラルが初めて検出されると、そのオブジェクトがヒープ上に作成され、そのオブジェクトへの参照が文字列リテラル プールに格納されます。
その後同じ文字列リテラルを使用すると、ヒープに新しい文字列オブジェクトを作成する代わりに、リテラル プールからの同じ文字列参照が使用されます。String が不変であることを考えると、これは安全です。同じ String オブジェクトへの参照を共有できます。したがって、確かにこれはより良いアプローチです。
やったほうがいい
map.put("two", "world");
#2 のアプローチでは、Oscar が述べたように、プールに既に存在する文字列を探すことなく、毎回新しい文字列を作成します。