ローカル変数の背後にある考え方は、それらが必要とされる限られたスコープ内にのみ存在するということです。そのため、値について、または少なくとも、その値がどこから来ているのかについて不確実性が生じる理由はほとんどないはずです。ローカル変数にデフォルト値があることから生じる多くのエラーを想像できます。
たとえば、次の単純なコードを考えてみましょう ...(明示的に初期化されていない場合、ローカル変数には指定されたデフォルト値が割り当てられていることをデモンストレーションの目的で想定します)
System.out.println("Enter grade");
int grade = new Scanner(System.in).nextInt(); //I won't bother with exception handling here, to cut down on lines.
char letterGrade; //let us assume the default value for a char is '\0'
if (grade >= 90)
letterGrade = 'A';
else if (grade >= 80)
letterGrade = 'B';
else if (grade >= 70)
letterGrade = 'C';
else if (grade >= 60)
letterGrade = 'D';
else
letterGrade = 'F';
System.out.println("Your grade is " + letterGrade);
すべてのことを言い終えたら、コンパイラーがletterGradeにデフォルト値 '\ 0'を割り当てたと仮定すると、このコードは記述されたとおりに正しく機能します。しかし、elseステートメントを忘れた場合はどうなりますか?
コードをテスト実行すると、次のような結果になる可能性があります
Enter grade
43
Your grade is
この結果は、予想通りでしたが、確かにコーダーの意図ではありませんでした。実際、おそらく大多数のケース(または少なくともそのかなりの数)では、デフォルト値は望ましい値ではないため、ほとんどの場合、デフォルト値はエラーになります。忘れによって引き起こさデバッグ悲しみので、それは、それを使用する前に、ローカル変数に初期値を割り当てるためにコーダを強制するために、より理にかなっている= 1
でfor(int i = 1; i < 10; i++)
遠くには、する必要がないで利便性を上回る= 0
中をfor(int i; i < 10; i++)
。
たとえば、オブジェクトがコンストラクターでチェックされた例外をスローする場合、try-catch-finallyブロックが少し乱雑になる可能性があることは事実です(ただし、実際にはcatch-22ではありません)。理由または別の方法では、最終的にブロックの最後でこのオブジェクトに対して何かを行う必要があります。これの完全な例は、閉じなければならないリソースを扱う場合です。
過去のこれを処理する1つの方法はそうかもしれません...
Scanner s = null; //declared and initialized to null outside the block. This gives us the needed scope, and an initial value.
try {
s = new Scanner(new FileInputStream(new File("filename.txt")));
int someInt = s.nextInt();
} catch (InputMismatchException e) {
System.out.println("Some error message");
} catch (IOException e) {
System.out.println("different error message");
} finally {
if (s != null) //in case exception during initialization prevents assignment of new non-null value to s.
s.close();
}
ただし、Java 7以降、この最後のブロックは、try-with-resourcesなどを使用して不要になりました。
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
つまり、(名前が示すように)これはリソースでのみ機能します。
そして、前者の例は少し不愉快ですが、これはおそらくローカル変数とそれらがどのように実装されているかについて話すよりも、try-catch-finallyやこれらのクラスが実装されている方法について多くを語っています。
フィールドがデフォルト値に初期化されることは事実ですが、これは少し異なります。たとえばと言うと、int[] arr = new int[10];
この配列を初期化するとすぐに、オブジェクトはメモリ内の指定された場所に存在します。しばらくの間、デフォルト値がないと仮定しましょう。代わりに、初期値は、その時点でそのメモリ位置にある1と0の連続です。これにより、多くの場合、非決定的な動作が発生する可能性があります。
あるとしましょう...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Same.
ある実行Not same.
で表示され、別の実行で表示される可能性があることは完全に可能です。参照変数について話し始めると、問題はさらに深刻になる可能性があります。
String[] s = new String[5];
定義によれば、sの各要素は文字列を指す必要があります(またはnullです)。ただし、初期値がこのメモリ位置で偶然発生する一連の0と1である場合、毎回同じ結果が得られる保証はないだけでなく、オブジェクトs [0]がポイントする保証もありません。 (それは意味のあるものを指すと仮定した場合)にも、ある文字列(おそらくそれはウサギだ、:P)!型に対するこの懸念の欠如は、JavaをJavaにするほとんどすべてのものに直面して飛行します。したがって、ローカル変数のデフォルト値を持つことはせいぜいオプションであると見なすことができますが、インスタンス変数のデフォルト値を持つことは必要性に近いです。