Dừng phân công lại biến
Mặc dù những câu trả lời này rất thú vị về mặt trí tuệ, tôi đã không đọc câu trả lời đơn giản ngắn:
Sử dụng từ khóa cuối cùng khi bạn muốn trình biên dịch ngăn chặn một biến được gán lại cho một đối tượng khác.
Cho dù biến là biến tĩnh, biến thành viên, biến cục bộ hoặc biến đối số / biến tham số, hiệu ứng hoàn toàn giống nhau.
Thí dụ
Chúng ta hãy xem hiệu quả trong hành động.
Hãy xem xét phương thức đơn giản này, trong đó hai biến ( arg và x ) đều có thể được gán lại các đối tượng khác nhau.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Đánh dấu biến cục bộ là cuối cùng . Điều này dẫn đến một lỗi biên dịch.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Thay vào đó, hãy đánh dấu biến tham số là cuối cùng . Điều này cũng dẫn đến một lỗi biên dịch.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Đạo đức của câu chuyện:
Nếu bạn muốn đảm bảo một biến luôn trỏ đến cùng một đối tượng, hãy đánh dấu biến cuối cùng .
Không bao giờ gán lại đối số
Là một thực hành lập trình tốt (trong bất kỳ ngôn ngữ nào), bạn không bao giờ nên gán lại một biến tham số / đối số cho một đối tượng khác với đối tượng được truyền bởi phương thức gọi. Trong các ví dụ trên, người ta không bao giờ nên viết dòng này arg =
. Vì con người mắc lỗi và lập trình viên là con người, chúng ta hãy yêu cầu trình biên dịch hỗ trợ chúng ta. Đánh dấu mọi biến tham số / tham số là 'cuối cùng' để trình biên dịch có thể tìm và gắn cờ mọi phép gán lại như vậy.
Khi nhìn lại
Như đã lưu ý trong các câu trả lời khác, mục tiêu thiết kế ban đầu của Java đưa ra là giúp các lập trình viên tránh các lỗi ngu ngốc như đọc qua phần cuối của mảng, Java nên được thiết kế để tự động thực thi tất cả các biến tham số / tham số là 'cuối cùng'. Nói cách khác, đối số không nên là biến . Nhưng tầm nhìn xa là tầm nhìn 20/20 và các nhà thiết kế Java đã có trong tay đầy đủ vào thời điểm đó.
Vì vậy, luôn luôn thêm final
vào tất cả các đối số?
Chúng ta có nên thêm final
vào từng tham số phương thức được khai báo không?
- Về lý thuyết, có.
- Trong thực tế, không.
Only final
Chỉ thêm khi mã của phương thức dài hoặc phức tạp, trong đó đối số có thể bị nhầm với biến cục bộ hoặc biến thành viên và có thể được gán lại.
Nếu bạn mua vào thực tế không bao giờ gán lại một đối số, bạn sẽ có xu hướng thêm một final
đối số. Nhưng điều này là tẻ nhạt và làm cho tuyên bố khó đọc hơn một chút.
Đối với mã đơn giản ngắn trong đó đối số rõ ràng là một đối số và không phải là biến cục bộ cũng không phải là biến thành viên, tôi không bận tâm thêm final
. Nếu mã khá rõ ràng, không có cơ hội nào cho tôi cũng như bất kỳ lập trình viên nào khác đang bảo trì hoặc tái cấu trúc lại vô tình nhầm nhầm biến đối số là một thứ khác hơn là một đối số, thì đừng bận tâm. Trong công việc của riêng tôi, tôi final
chỉ thêm vào mã dài hơn hoặc nhiều hơn có liên quan trong đó một đối số có thể bị nhầm với biến cục bộ hoặc biến thành viên.
Một trường hợp khác được thêm vào cho sự hoàn chỉnh
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}