12

簡単な質問が1つあります。通常、私は次のようなコードを記述します。

String myString = "hello";

for (int i=0, i<10; i++)
{
  myString = "hello again";
}

次のスタイルは、不要なオブジェクトが多すぎるため、適切なスタイルではないと思います。

for (int i=0, i<10; i++)
{
  String myString = "hello again";
}

これも正しいですか?それとも、私が作成したクラスからのオブジェクトのような明示的なオブジェクトを取得した場合だけですか?ブール値または整数の場合はどうなりますか?より良いコーディングスタイルは何ですか?ループの前に一度インスタンス化してループで使用しますか、それともループで毎回再度インスタンス化しますか?なぜ?プログラムが高速であるか、使用されるストレージが少ないため、または...?

誰かが私に言った、それがブール値であるなら、私はそれをループで直接インスタンス化するべきだ。彼は、ヒープに違いはなく、変数がループ内に属していることがより明確になると述べました。では、何が正しいのでしょうか?

答えてくれてありがとう!:-)

====

すべての回答をありがとう!

結論として、可能な限り最小のスコープ内でオブジェクトを宣言することが望ましいです。すべてのループでオブジェクトが再インスタンス化された場合でも、ループの外側でオブジェクトを宣言してインスタンス化しても、パフォーマンスは向上しません。

4

7 に答える 7

15

いいえ、後者のコードは実際には有効ではありません。ただし、中かっこを使用します。

for (int i=0; i<10; i++)
{
    String myString = "hello again";
}

if(基本的に、ステートメント、ループなどの単一ステートメント本体として変数宣言を使用することはできません。)

それは無意味ですが、有効です-そして最初のバージョンであるIMOよりも望ましいです。これ以上のメモリは必要ありませんが、一般的には、ローカル変数にできるだけ狭い範囲を指定し、できるだけ遅く宣言し、理想的には同じポイントで初期化することをお勧めします。これにより、各変数をどこで使用できるかが明確になります。

もちろん、ループの外側(前後)で変数を参照する必要がある場合は、ループの外側でも変数を宣言する必要があります。

効率を考慮するときは、変数オブジェクトを区別する必要があります。上記のコードは、最大で1つのオブジェクト(リテラル「helloagain」によって参照されるStringオブジェクト)を使用します。

于 2012-05-09T19:38:27.930 に答える
3

Binyamin Sharet が述べたように、一般的に、可能な限り最小のスコープ内で変数を宣言する必要があります。特定の例では、ループ外の変数にアクセスする必要がない限り、2 番目の例が一般的に望ましいです。

ただし、特定の条件下では、これはパフォーマンスに影響を与える可能性があります。つまり、同じオブジェクトを何度もインスタンス化する場合です。あなたの特定の例では、Java の文字列リテラルの自動プールの恩恵を受けています。しかし、ループの反復ごとに同じオブジェクトの新しいインスタンスを実際に作成していて、このループが何百回も何千回も実行されていたとします。

for (int i=0, i<1000; i++)
{
  String myString = new String("hello again"); // 1000 Strings are created--one on every iteration
  ...
}

ループが何百回または何千回もループしているが、たまたま同じオブジェクトを何度もインスタンス化している場合、ループ内でインスタンス化すると、多くの不要なガベージ コレクションが発生します。反復ごとに新しいオブジェクトを削除します。その場合、ループの外で変数を宣言してインスタンス化する方がよいでしょう。

String myString = new String("hello again"); // only one String is created

for (int i=0, i<1000; i++)
{
  ...
}

そして、完全に循環させるために、コードの関連するセクションの周りに余分な中括弧を追加して、スコープを手動で制限できます。

{ // Limit the scope
  String myString = new String("hello again");

  for (int i=0, i<1000; i++)
  {
    ...
  }
}
于 2012-05-09T20:04:18.200 に答える
1

あなたが意味declareしているように見えinstantiateますが、一般的には、必要な最小のスコープ(この場合はループ内)で変数を宣言する必要があります。

于 2012-05-09T19:37:58.603 に答える
1

forループの外側で変数を使用する場合は、外側で宣言します。それ以外の場合は、スコープを最小限に抑えることをお勧めします。

于 2012-05-09T19:39:39.643 に答える
1

2番目の問題は、オブジェクトを作成し、誰か(GC)がそれらをクリーンアップする必要があることです。もちろん、10回の反復では重要ではありません。

ところで、私が書いたあなたの特定の例では

    String myString = null; 
    final String HELLO_AGAIN="hello again";
    for (int i=0; i<10; i++)
      myString = HELLO_AGAIN;
于 2012-05-09T19:51:55.973 に答える
0

値が変更されない限り、ループの外側で確実にインスタンス化する必要があります。

于 2012-05-09T19:38:16.107 に答える
0

ここでの問題は、String が不変オブジェクトであることです。文字列の値を変更することはできず、新しい String オブジェクトを作成することしかできません。いずれにせよ、変数に新しいオブジェクト インスタンスを割り当てることが目標である場合は、スコープを制限し、ループの本体内で宣言します。

オブジェクトが変更可能な場合、ループの次の反復ごとにオブジェクトを再利用し、必要な属性を変更するだけで十分です。この概念は、同じクエリを複数回実行するために使用されますが、パラメーターが異なる場合は、PreparedStatement を使用します。

極端な場合、アプリケーション全体で共有できるオブジェクトのプールを維持することさえあります。リソースが不足すると追加のオブジェクトを作成し、妥当な量の未使用を検出すると縮小します。この概念は、接続プールを維持するために使用されます。

于 2013-04-07T18:06:31.207 に答える