Tôi nghĩ bạn đã tiếp xúc với một câu hỏi quan trọng hơn sau câu hỏi gốc: bạn nên làm việc để ngăn chặn các trường hợp ngoại lệ trong getters và setters?
Câu trả lời là có, bạn nên làm việc để tránh các ngoại lệ nhỏ.
Những gì bạn có ở đây là một cách hiệu quả lazy instantiation mà không phải là ở tất cả các động cơ trong ví dụ này:
Trong lập trình máy tính, khởi tạo lười biếng là chiến thuật trì hoãn việc tạo ra một đối tượng, tính toán của một giá trị hoặc một số quá trình khác tốn kém cho đến lần đầu tiên cần thiết.
Bạn có hai vấn đề trong ví dụ này:
dụ của bạn không phải là thread an toàn. Việc kiểm tra null đó có thể thành công (tức là, tìm ra rằng đối tượng là null) trên hai luồng cùng một lúc. Sự khởi tạo của bạn sau đó tạo ra hai danh sách chuỗi khác nhau. Hành vi không xác định sẽ xảy ra.
Không có lý do chính đáng trong ví dụ này để trì hoãn việc khởi tạo. Nó không phải là một hoạt động đắt tiền hoặc phức tạp. Đây là những gì tôi có nghĩa là "làm việc để tránh ngoại lệ tầm thường": nó là giá trị đầu tư chu kỳ để tạo ra một hữu ích (nhưng trống) danh sách để đảm bảo rằng bạn không ném chậm detonation null con trỏ ngoại lệ xung quanh.
Hãy nhớ rằng, khi bạn gây ra một ngoại lệ trên mã bên ngoài, bạn về cơ bản hy vọng các nhà phát triển biết làm thế nào để làm một cái gì đó hợp lý với nó. Bạn cũng đang hy vọng rằng không có một nhà phát triển thứ ba trong phương trình có bọc tất cả mọi thứ trong một eater ngoại lệ, chỉ để nắm bắt và bỏ qua ngoại lệ như của bạn:
try {
// I don't understand why this throws an exception. Ignore.
t.getStrings();
} catch (Exception e) {
// Ignore and hope things are fine.
}
Trong ví dụ dưới đây, tôi đang sử dụng Null Object pattern để cho biết mã tương lai mà ví dụ của bạn chưa được đặt. Tuy nhiên, đối tượng Null chạy như mã không đặc biệt và, do đó, không có chi phí và tác động đến luồng công việc của các nhà phát triển trong tương lai.
public class App {
static class Test {
// Empty list
public static final List<String> NULL_OBJECT = new ArrayList<String>();
private List<String> strings = NULL_OBJECT;
public synchronized List<String> getStrings() {
return strings;
}
public synchronized void setStrings(List<String> strings) {
this.strings = strings;
}
}
public static void main(String[] args) {
Test t = new Test();
List<String> s = t.getStrings();
if (s == Test.NULL_OBJECT) {
// Do whatever is appropriate without worrying about exception
// handling.
// A possible example below:
s = new ArrayList<String>();
t.setStrings(s);
}
// At this point, s is a useful reference and
// t is in a consistent state.
}
}
Nguồn
2011-09-07 13:35:45
không sao - nhưng tại sao nó lại tệ? – wulfgarpro
@wulfgar: vì bạn nên đảm bảo rằng các đối tượng của bạn luôn ở trạng thái hợp lệ. nếu bạn chắc chắn rằng bạn không bao giờ cho phép một đối tượng ở trạng thái không hợp lệ, bạn luôn có thể nhận được các thuộc tính của nó mà không phải lo lắng rằng có thể có điều gì đó sai. cộng với bạn chỉ phải kiểm tra mọi thứ một lần (trong các setters). –
Không cho phép biết được trạng thái bất hợp pháp của cài đặt không được gọi. –