2010-09-14 27 views
7

Tôi đang sử dụng thư viện của bên thứ ba trả về một Iterator thô, ví dụ:Duyệt an toàn một Iterator thô trong Java?

Iterator<?> children = element.getChildElements(); 

Tôi biết loại thực tế, nhưng tôi không nhất thiết phải tin tưởng lib của bên thứ ba dính vào nó trong tương lai. Có hai (mà tôi có thể nghĩ ra) hơi rủi ro cách để đi qua này:

@SuppressWarnings("unchecked") 
Iterator<ActualObject> currentChildren = (Iterator<ActualObject>)currentElement.getChildElements(); 

hoặc

Iterator<?> children = element.getChildElements(); 
while (null != children && children.hasNext()) { 
    ActualObject child = (ActualObject)children.next(); //Possible ClassCastException @ runtime 
    ... 
} 

Các chỉ "an toàn" cách tôi có thể đưa ra để đi qua loại này iterator là như sau:

Iterator<?> children = element.getChildElements(); 
while (null != children && children.hasNext()) { 
    Object obj = children.next(); 
    ActualObject child = null; 
    if (obj instanceof ActualObject) 
     child = (ActualObject)obj; 
    ... 
} 

Điều này có vẻ quá chi tiết. Có cách nào tốt hơn, nhưng không kém phần "an toàn" để duyệt qua một trình vòng lặp thô?

EDIT: Tôi nhận ra mình có thể bắt/ghi ngoại lệ trong một khối khác, tôi đang tìm kiếm (hy vọng) cho một ngôn ngữ Java tương đương với những gì ColinD đã đề cập dưới đây.

+0

Bạn muốn điều gì xảy ra nếu có các đối tượng được trình lặp lặp lại có * không * thể hiện của 'ActualObject'? – pkaeding

+0

Cần làm gì nếu loại trẻ không phải là ActualObject? Nếu bạn không cần tiến hành, tôi nghĩ rằng việc bắt ClassCastException có thể là cách tốt nhất để đi. Bạn có thể đăng nhập loại không phù hợp và tiếp tục. – Gangadhar

+0

@pkaeding & @Gangadhar - Tôi sẽ ném một ngoại lệ. –

Trả lời

7

Guava giúp việc này trở nên dễ dàng với phương thức Iterators.filter(Iterator<?>, Class<T>). Nó trả về một unmodifiable Iterator<T> rằng về cơ bản chỉ là bỏ qua mọi phần tử của iterator cho rằng không phải là một thể hiện của loại T:

Iterator<ActualObject> children = Iterators.filter(element.getChildElements(), 
    ActualObject.class); 

Bạn rõ ràng là có thể sau đó đi qua các iterator kết quả mà không cần phải đúc từng yếu tố để ActualObject VÀ mà không phải lo lắng về ClassCastException.

+0

Cảm ơn, điều đó thật thú vị, nhưng tiếc là sử dụng Ổi không phải là một lựa chọn cho tôi. –

+1

@Segphault: sau đó đọc mã nguồn và kiểm tra xem họ đã làm như thế nào. –

+0

Tôi nghi ngờ họ đã làm điều tương tự như ví dụ cuối cùng của bạn, nhưng chỉ trích xuất nó vào một đối tượng bao bọc. – pkaeding

2

Cách dễ dàng để giải quyết vấn đề là chỉ truyền và đảm bảo rằng, nếu loại thay đổi từ những gì bạn mong đợi trong tương lai, ngoại lệ sẽ được ném và bạn sẽ được thông báo. Bạn sẽ muốn kiểm tra rằng tuy nhiên bạn đang đăng nhập ngoại lệ hoạt động và ngoại lệ sẽ tìm đường đến tệp nhật ký. Trường hợp ngoại lệ tồn tại để cho bạn biết một cái gì đó không phải là những gì bạn mong đợi, hãy để họ làm công việc của họ.

Nếu bạn âm thầm bỏ qua các yếu tố không phải là loại mong muốn thì bạn có thể bỏ lỡ dữ liệu bạn cần, điều đó nghe không giống như một giải pháp tốt cho tôi.

+2

I đồng ý với phần thứ hai –

2

phiên bản cuối cùng của bạn có vẻ như con đường để đi nhưng tôi đoán chúng tôi có thể cải thiện một chút:

Iterator<?> children = element.getChildElements(); 
// no null check needed. If an api that supposedly 
// returns an iterator actually returns null, it's a bad 
// API, don't use it 
while (children.hasNext()) { 
    Object obj = children.next(); 
    if (obj instanceof ActualObject) 
     doStuffWith((ActualObject)obj); 
    // we know it's of the right type so we might 
    // as well put the cast in the method call. 
} 

Vì vậy, nó nắm này:

Iterator<?> children = element.getChildElements(); 
while (children.hasNext()) { 
    Object obj = children.next(); 
    if (obj instanceof ActualObject) 
     doStuffWith((ActualObject)obj); 
} 

mà tôi muốn nói isn không quá tệ.

Chỉnh sửa:

Cũng có thể có một khối khác bên dưới khối nếu quá. cái gì đó dọc theo dòng:

else{ 
    log.warn("Expected type: " + ActualObject.class + ", but got " + obj); 
} 
+0

Bạn đang đúng về việc kiểm tra null, tôi sẽ loại bỏ điều đó. Đó là một API xấu, theo nhiều cách hơn là được chứng minh bằng câu hỏi. Tôi không thể chờ đợi để không bao giờ sử dụng nó một lần nữa. –

1

Kể từ khi có vẻ như bạn muốn dừng thực hiện và ném một ngoại lệ nếu bạn gặp phải một đối tượng được trả về bởi các iterator đó không phải là một thể hiện của ActualObject, sau đó tôi sẽ chỉ cast nó và có một khối đánh bắt để xử lý ClassCastException có thể có.

Các vấn đề liên quan