Tôi xem xét final
trong các tham số phương thức và các biến cục bộ là nhiễu mã. Các khai báo phương thức Java có thể khá dài (đặc biệt là với các tổng quát) - không cần phải thực hiện chúng nữa.
Nếu các bài kiểm tra đơn vị được viết đúng, việc gán cho các tham số "có hại" sẽ được chọn, do đó nó không bao giờ thực sự là một vấn đề. Sự rõ ràng trực quan quan trọng hơn việc tránh một lỗi có thể không xảy ra do các bài kiểm tra đơn vị của bạn không đủ độ bao phủ.
Các công cụ như FindBugs và CheckStyle có thể được cấu hình để phá vỡ bản dựng nếu việc gán được thực hiện cho các tham số hoặc biến cục bộ, nếu bạn quan tâm sâu sắc đến những điều đó.
Tất nhiên, nếu bạn cần làm cho chúng cuối cùng, ví dụ vì bạn đang sử dụng giá trị trong một lớp ẩn danh, thì không vấn đề gì - đó là giải pháp sạch đơn giản nhất.
Ngoài hiệu quả rõ ràng của việc thêm các từ khóa bổ sung vào các tham số của bạn và do đó IMHO ngụy trang chúng, việc thêm các tham số cuối cùng vào phương thức thường có thể làm cho mã trong thân phương thức trở nên khó đọc hơn, làm cho mã kém hơn - trở thành "tốt", mã phải dễ đọc và đơn giản nhất có thể. Đối với một ví dụ giả định, giả sử tôi có một phương pháp cần xử lý tình huống không nhạy cảm.
Không có final
:
public void doSomething(String input) {
input = input.toLowerCase();
// do a few things with input
}
Đơn giản. Dọn dẹp. Mọi người đều biết chuyện gì đang xảy ra.
Bây giờ với 'trận chung kết', tùy chọn 1:
public void doSomething(final String input) {
final String lowercaseInput = input.toLowerCase();
// do a few things with lowercaseInput
}
Trong khi thực hiện các tham số final
ngăn bộ mã hóa thêm mã xuống khỏi suy nghĩ rằng anh ta đang làm việc với giá trị ban đầu, có một rủi ro tương đương mà mã tiếp tục có thể sử dụng input
thay vì lowercaseInput
, điều đó không nên và không thể bảo vệ, bởi vì bạn có thể ' t mang nó ra khỏi phạm vi (hoặc thậm chí gán null
cho input
nếu đó thậm chí sẽ giúp anyway).
Với 'trận chung kết', tùy chọn 2:
public void doSomething(final String input) {
// do a few things with input.toLowerCase()
}
Bây giờ chúng tôi vừa tạo ra nhiều tiếng ồn mã hơn và giới thiệu một cú đánh hiệu suất là phải gọi toLowerCase()
n lần.
Với 'trận chung kết', tùy chọn 3:
public void doSomething(final String input) {
doSomethingPrivate(input.toLowerCase());
}
/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
if (!input.equals(input.toLowerCase())) {
throw new IllegalArgumentException("input not lowercase");
}
// do a few things with input
}
Nói về tiếng ồn mã. Đây là một con tàu đắm. Chúng tôi đã có một phương thức mới, một khối ngoại lệ bắt buộc, bởi vì mã khác có thể gọi nó không chính xác. Nhiều bài kiểm tra đơn vị để bao gồm ngoại lệ. Tất cả để tránh một dòng đơn giản, và IMHO thích hợp và vô hại.
Ngoài ra còn có một vấn đề là các phương thức không nên dài đến mức bạn không thể dễ dàng nhìn thấy nó và biết trong nháy mắt rằng việc gán tham số đã diễn ra.
Tôi nghĩ rằng đó là một cách thực hành / phong cách tốt mà nếu bạn gán cho một tham số, bạn thực hiện nó sớm trong phương thức, tốt nhất là dòng đầu tiên hoặc ngay sau khi kiểm tra đầu vào cơ bản, thay thế nó cho toàn bộ phương thức, có hiệu quả nhất quán trong phương pháp. Người đọc biết để mong đợi bất kỳ sự chuyển nhượng nào là rõ ràng (gần tuyên bố chữ ký) và ở một nơi nhất quán, điều này làm giảm đáng kể vấn đề mà việc thêm vào cuối cùng đang cố gắng tránh. Trên thực tế tôi hiếm khi gán cho các tham số, nhưng nếu tôi làm thì tôi luôn làm nó ở đầu một phương thức.
Cũng lưu ý rằng final
không thực sự bảo vệ bạn như lúc đầu có vẻ như:
public void foo(final Date date) {
date.setTime(0);
// code that uses date
}
final
không hoàn toàn bảo vệ bạn trừ khi loại tham số là nguyên thủy hoặc bất biến.