web-dev-qa-db-ja.com

Javaでは、変数は関数の先頭で宣言する必要がありますか、それとも必要に応じて宣言する必要がありますか?

後で必要になるように宣言するのではなく、すべての変数を最初に宣言し、それらをnull/0/whatに初期化することによって関数を開始する人のために、Javaコードをクリーンアップしていますオン。

これに関する具体的なガイドラインは何ですか?いずれかの方法で最適化の理由はありますか、それとも一方通行は単に良い習慣ですか?それを行う適切な方法が何であれ、それから逸脱することが許容される場合はありますか?

36
Ken

変数を、使用する最初の場所にできるだけ近づけて宣言します。これは実際には効率とは何の関係もありませんが、コードをはるかに読みやすくします。変数が使用される場所に宣言されている変数に近いほど、後でコードを読み取るときに実行する必要があるスクロール/検索が少なくなります。使用される最初のスポットに近い変数を宣言すると、当然、変数が狭くなります scope

84
Bill the Lizard

適切な方法は、変数を最初に使用したときに正確に宣言し、コードを理解しやすくするためにスコープを最小化することです。

関数の先頭で変数を宣言することは、C(必要な場合)からの引き継ぎであり、まったく利点はありません(変数スコープはソースコードにのみ存在し、バイトコードではすべてのローカル変数がスタック上に順番に存在します)。決してそれをしないでください。

一部の人々は、それが「きちんとした」と主張することによって慣行を擁護しようとするかもしれませんが、メソッド内でコードを「整理」する必要があることは、通常、メソッドが単に長すぎることを強く示しています。

34

Javaコード規約宣言の第6章 から:

6.3配置

ブロックの先頭にのみ宣言を配置します。 (ブロックは、中括弧「{」と「}」で囲まれたコードです。)変数を最初に使用するまで宣言するのを待たないでください。不注意なプログラマーを混乱させ、スコープ内のコードの移植性を妨げる可能性があります。

void myMethod() {
    int int1 = 0;         // beginning of method block

    if (condition) {
        int int2 = 0;     // beginning of "if" block
        ...
    }
}

ルールの1つの例外は、forループのインデックスです。これはJavaで、forステートメントで宣言できます。

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

より高いレベルで宣言を隠すローカル宣言は避けてください。たとえば、内部ブロックで同じ変数名を宣言しないでください。

int count;
...
myMethod() {
    if (condition) {
        int count = 0;     // AVOID!
        ...
    }
    ...
}
20
Tim

関数の本体内のさまざまな孤立した場所で数十億の変数が使用されている場合、関数は大きすぎます。

関数が快適に理解できるサイズである場合、「すべて前」と「必要に応じて」の間に違いはありません。

唯一の先行変数は、forステートメントの本体にあります。

for( Iterator i= someObject.iterator(); i.hasNext(); ) 
14
S.Lott

必要以上に広い範囲で変数を定義すると、理解がかなり妨げられます。限定スコープは、この変数がこの小さなコードブロックに対してのみ意味を持ち、さらに読むときは考えられないことを示します。これは、脳が持っている小さな短期作業記憶のために非常に重要な問題です(平均して7つのことしか追跡できないと言われています)。追跡することが1つ少ないことが重要です。

同様に、あなたは本当に文字通りの意味で変数を避けるように努めるべきです。すべてのものを一度割り当てて、最終的に宣言して、読者にわかるようにしてください。何かが変化したかどうかで追跡する必要がないため、認知負荷が実際に削減されます。

5
Ants Aasma

必要に応じて宣言すると、最初に宣言するよりも間違いが少なくなることがわかりました。また、間違いを防ぐために、可能な限り最小限の範囲でそれらを宣言することもわかりました。

数年前に宣言の場所によって生成されたバイトコードを調べたところ、多かれ少なかれ同一であることがわかりました。いつ割り当てられたかによって、時折違いがありました。次のようなものでも:

for(Object o : list) {
   Object temp = ...;  //was not "redeclared" every loop iteration
}

vs

Object temp;
for(Object o : list) {
   temp = ...; //nearly identical bytecoode, if not exactly identical.
}

多かれ少なかれ同一になりました

5
James Schek

私は今、これとまったく同じことをしています。私が作り直しているコード内のすべての変数は、関数の先頭で宣言されています。これを調べていると、いくつかの変数が宣言されているが、使用されていないか、宣言されて操作が行われていることがわかりました(つまり、Stringを解析してから、Calendarオブジェクトに日付/時刻の値を設定します。 string)ただし、結果のCalendarオブジェクトは使用されません。

宣言を上から取得し、関数内で使用場所に近い場所に移動することで、これらを調べてクリーンアップしています。

5
Jeremy Cron

トップ宣言スタイルの方がエラーが発生しやすいことは、実際には客観的に証明できると思います。

ランダムに行を移動してどちらかのスタイルでコードを変異テストする場合(マージがうまくいかなかったり、意図せずにカットアンドペーストしたりすることをシミュレートするため)、declare-at-the-top-styleは機能的に間違っているにもかかわらずコンパイルされる可能性が高くなります。

私は、declare-at-the-topには、個人的な好みに帰着しない対応する利点があるとは思いません。

したがって、信頼できるコードを記述したい場合は、ジャストインタイム宣言を行うことを選択することを学びます。

4
soru

From Google Javaスタイルガイド

4.8.2.2必要に応じて宣言

ローカル変数は、それらを含むブロックまたはブロックのような構造の開始時に習慣的に宣言されません。代わりに、ローカル変数は、スコープを最小化するために、最初に使用されたポイントの近くで(理由の範囲内で)宣言されます。ローカル変数の宣言には通常、初期化子があるか、宣言の直後に初期化されます。

まあ、私はグーグルがしていることに従います、表面的なレベルでは、メソッド/関数の上部ですべての変数を宣言することは「きれい」であるように見えるかもしれません、必要に応じて変数を宣言することが有益であることは非常に明白です。それは主観的なものですが、直感的に感じるものは何でも。

4

原則:ローカル変数宣言は、単にメソッドの先頭に配置するのではなく、最初の使用にできるだけ近づけて配置します。この例を考えてみましょう。

/** Return true iff s is a blah or a blub. */
public boolean checkB(String s) {
    // Return true if s is a blah
    ... code to return true if s is a blah ... 

    // Return true if s is a blub. */
    int helpblub= s.length() + 1;
    ... rest of code to return true is s is a blah.

    return false;
}

ここで、ローカル変数helpblubは、sがblubであるかどうかをテストするために、コード内の必要な場所に配置されます。これは、「Return true is s is ablub」を実装するコードの一部です。 helpblubの宣言をメソッドの最初のステートメントとして配置することは、まったく論理的に意味がありません。貧しい読者は、なぜその変数がそこにあるのか疑問に思うでしょう。それは何のため?

4
David Gries

これは、パフォーマンスではなく可読性と個人的な好みの問題です。コンパイラは気にせず、とにかく同じコードを生成します。

2

関数の上部と下部で宣言する人を見てきました。すぐに見えるトップが好きです。それは選択と好みの問題です。

1
pave