Ý tưởng đằng sau các biến cục bộ là chúng chỉ tồn tại trong phạm vi giới hạn mà chúng cần thiết. Như vậy, sẽ có rất ít lý do cho sự không chắc chắn về giá trị, hoặc ít nhất, giá trị đó đến từ đâu. Tôi có thể hình dung ra nhiều lỗi phát sinh do có giá trị mặc định cho các biến cục bộ.
Ví dụ: hãy xem xét đoạn mã đơn giản sau ... ( NB hãy giả sử cho mục đích trình diễn rằng các biến cục bộ được gán một giá trị mặc định, như được chỉ định, nếu không được khởi tạo rõ ràng )
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);
Khi tất cả được nói và hoàn thành, giả sử trình biên dịch đã gán giá trị mặc định là '\ 0' cho letterGrade , mã này như được viết sẽ hoạt động bình thường. Tuy nhiên, nếu chúng ta quên câu lệnh else thì sao?
Việc chạy thử mã của chúng tôi có thể dẫn đến kết quả sau
Enter grade
43
Your grade is
Kết quả này, trong khi được mong đợi, chắc chắn không phải là ý định của các coder. Thật vậy, có lẽ trong phần lớn các trường hợp (hoặc ít nhất là một số đáng kể), giá trị mặc định sẽ không phải là giá trị mong muốn , vì vậy trong đại đa số trường hợp, giá trị mặc định sẽ dẫn đến lỗi. Nó làm cho ý nghĩa hơn để buộc các coder để gán một giá trị ban đầu cho một biến địa phương trước khi sử dụng nó, vì đau buồn gỡ lỗi do quên = 1
trong for(int i = 1; i < 10; i++)
xa outweighs sự tiện lợi trong không cần phải bao gồm = 0
trong for(int i; i < 10; i++)
.
Đúng là các khối try-catch-last có thể hơi lộn xộn (nhưng nó không thực sự là một khối catch-22 như câu trích dẫn dường như gợi ý), khi một đối tượng ném một ngoại lệ đã được kiểm tra vào hàm tạo của nó, nhưng đối với một lý do khác, một cái gì đó phải được thực hiện với đối tượng này ở cuối khối cuối cùng. Một ví dụ hoàn hảo về điều này là khi xử lý tài nguyên, tài nguyên này phải được đóng lại.
Một cách để xử lý điều này trong quá khứ có thể là như vậy ...
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();
}
Tuy nhiên, đối với Java 7, khối cuối cùng này không còn cần thiết khi sử dụng try-with-resources, như vậy.
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
Điều đó nói rằng, (như tên cho thấy) điều này chỉ hoạt động với các tài nguyên.
Và trong khi ví dụ trước là một chút may mắn, điều này có lẽ nói lên cách try-catch-last hoặc các lớp này được triển khai hơn là nó nói về các biến cục bộ và cách chúng được triển khai.
Đúng là các trường được khởi tạo thành giá trị mặc định, nhưng điều này hơi khác một chút. Ví dụ: khi bạn nói, int[] arr = new int[10];
ngay sau khi bạn khởi tạo mảng này, đối tượng sẽ tồn tại trong bộ nhớ tại một vị trí nhất định. Hãy giả sử một lúc rằng không có giá trị mặc định, nhưng thay vào đó giá trị ban đầu là bất kỳ chuỗi số 1 và số 0 nào xảy ra ở vị trí bộ nhớ đó vào lúc này. Điều này có thể dẫn đến hành vi không xác định trong một số trường hợp.
Giả sử chúng ta có ...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Nó hoàn toàn có Same.
thể được hiển thị trong một lần chạy và Not same.
có thể được hiển thị trong một lần khác. Vấn đề có thể trở nên nghiêm trọng hơn khi bạn bắt đầu nói về các biến tham chiếu.
String[] s = new String[5];
Theo định nghĩa, mỗi phần tử của s phải trỏ đến một Chuỗi (hoặc là null). Tuy nhiên, nếu giá trị ban đầu là bất kỳ chuỗi số 0 và 1 nào xảy ra tại vị trí bộ nhớ này, thì không những không có gì đảm bảo rằng bạn sẽ nhận được cùng một kết quả mỗi lần, mà còn không có gì đảm bảo rằng đối tượng s [0] điểm thành (giả sử nó trỏ đến bất cứ thứ gì có ý nghĩa) thậm chí là Chuỗi (có lẽ đó là Thỏ,: p )! Sự thiếu quan tâm đến kiểu này sẽ bay khi đối mặt với khá nhiều thứ tạo nên Java Java. Vì vậy, mặc dù có giá trị mặc định cho các biến cục bộ có thể được xem là tùy chọn tốt nhất, nhưng việc có các giá trị mặc định cho các biến cá thể là điều cần thiết hơn .