Nói chung, không sử dụng các khối khởi tạo không tĩnh (và có thể tránh các khối tĩnh quá).
Cú pháp khó hiểu
Nhìn vào câu hỏi này, có 3 câu trả lời, nhưng bạn đã đánh lừa 4 người với cú pháp này. Tôi là một trong số họ và tôi đã viết Java được 16 năm! Rõ ràng, cú pháp có khả năng dễ bị lỗi! Tôi sẽ tránh xa nó.
Kính viễn vọng
Đối với những thứ thực sự đơn giản, bạn có thể sử dụng các hàm tạo "kính thiên văn" để tránh sự nhầm lẫn này:
public class Test {
private String something;
// Default constructor does some things
public Test() { doStuff(); }
// Other constructors call the default constructor
public Test(String s) {
this(); // Call default constructor
something = s;
}
}
Mô hình xây dựng
Nếu bạn cần doStuff () ở cuối mỗi hàm tạo hoặc khởi tạo tinh vi khác, có lẽ một mẫu trình xây dựng sẽ là tốt nhất. Josh Bloch liệt kê một số lý do tại sao các nhà xây dựng là một ý tưởng tốt. Các nhà xây dựng mất một ít thời gian để viết, nhưng viết đúng, họ là một niềm vui để sử dụng.
public class Test {
// Value can be final (immutable)
private final String something;
// Private constructor.
private Test(String s) { something = s; }
// Static method to get a builder
public static Builder builder() { return new Builder(); }
// builder class accumulates values until a valid Test object can be created.
private static class Builder {
private String tempSomething;
public Builder something(String s) {
tempSomething = s;
return this;
}
// This is our factory method for a Test class.
public Test build() {
Test t = new Test(tempSomething);
// Here we do your extra initialization after the
// Test class has been created.
doStuff();
// Return a valid, potentially immutable Test object.
return t;
}
}
}
// Now you can call:
Test t = Test.builder()
.setString("Utini!")
.build();
Vòng lặp khởi tạo tĩnh
Tôi đã từng sử dụng các trình khởi tạo tĩnh rất nhiều, nhưng đôi khi chạy vào các vòng lặp trong đó 2 lớp phụ thuộc vào các khối khởi tạo tĩnh của nhau được gọi trước khi lớp có thể được tải đầy đủ. Điều này tạo ra một "không tải lớp" hoặc thông báo lỗi mơ hồ tương tự. Tôi đã phải so sánh các tệp với phiên bản làm việc đã biết cuối cùng trong kiểm soát nguồn để tìm ra vấn đề là gì. Không có niềm vui nào cả.
Khởi tạo lười biếng
Có thể các trình khởi tạo tĩnh tốt cho lý do hiệu suất khi chúng hoạt động và không quá khó hiểu. Nhưng nói chung, tôi thích khởi tạo lười biếng hơn so với khởi tạo tĩnh trong những ngày này. Rõ ràng những gì họ làm, tôi chưa gặp phải lỗi tải lớp với họ và họ làm việc trong nhiều tình huống khởi tạo hơn các khối khởi tạo.
Định nghĩa dữ liệu
Thay vì khởi tạo tĩnh để xây dựng cấu trúc dữ liệu, (so sánh với các ví dụ trong các câu trả lời khác), giờ đây tôi sử dụng các hàm trợ giúp định nghĩa dữ liệu bất biến của Paguro :
private ImMap<String,String> days =
map(tup("mon", "monday"),
tup("tue", "tuesday"),
tup("wed", "wednesday"),
tup("thu", "thursday"),
tup("fri", "friday"),
tup("sat", "saturday"),
tup("sun", "sunday"));
Conculsion
Khi bắt đầu Java, các khối khởi tạo là cách duy nhất để thực hiện một số thứ, nhưng bây giờ chúng khó hiểu, dễ bị lỗi và trong hầu hết các trường hợp đã được thay thế bằng các lựa chọn thay thế tốt hơn (chi tiết ở trên). Thật thú vị khi biết về các khối khởi tạo trong trường hợp bạn thấy chúng trong mã kế thừa hoặc chúng xuất hiện trong một thử nghiệm, nhưng nếu tôi đang thực hiện đánh giá mã và tôi thấy một mã trong mã mới, tôi sẽ yêu cầu bạn giải thích tại sao không có mã nào các lựa chọn thay thế ở trên là phù hợp trước khi đưa ra mã của bạn.