2008-10-09 23 views
6

Tôi đang cố gắng để nắm bắt một ClassCastException khi deserializing một đối tượng từ xml.Làm thế nào để tôi bắt được ClassCastException?

Vì vậy,

try { 
    restoredItem = (T) decoder.readObject(); 
} catch (ClassCastException e){ 
    //don't need to crash at this point, 
    //just let the user know that a wrong file has been passed. 
} 

Tuy nhiên điều này sẽ không phải là trường hợp ngoại lệ không bị bắt. Bạn đề nghị điều gì?

+0

Được gắn thẻ lại để sử dụng các thẻ ngoại lệ phổ biến hơn. –

Trả lời

8

Mã trong câu hỏi sẽ cung cấp cho bạn cảnh báo truyền được bỏ chọn. Nghe -Xlint.

Tất cả trình biên dịch đều biết về T là giới hạn của nó, mà nó có thể không có (ngoài việc mở rộng đối tượng một cách rõ ràng và một siêu loại trống). Vì vậy, hiệu quả các diễn viên tại thời gian chạy là (Object) - không phải là rất hữu ích.

Những gì bạn có thể làm là chuyển vào một thể hiện của Lớp của kiểu được tham số hóa (giả sử nó không phải là chung).

class MyReader<T> { 
    private final Class<T> clazz; 
    MyReader(Class<T> clazz) { 
     if (clazz == null) { 
      throw new NullPointerException(); 
     } 
     this.clazz = clazz; 
    } 
    public T restore(String from) { 
     ... 
     try { 
      restoredItem = clazz.cast(decoder.readObject()); 
      ... 
      return restoredItem; 
     } catch (ClassCastException exc) { 
      ... 
     } 
    } 
} 

Hoặc như một phương pháp chung:

public <T> T restore(Class<T> clazz, String from) { 
     ... 
     try { 
      restoredItem = clazz.cast(decoder.readObject()); 
      ... 
0

Vâng, tôi không thể sử dụng instanceof điều hành như phương pháp này là một parametrized một:

public T restore(String from){ 
... 
restoredItem = (T) decoder.readObject(); 
... 
} 

Và Generics trong Java là thời gian biên dịch chỉ.

+0

Điều đó không có nghĩa là dàn diễn viên cho T thực sự được thực hiện bởi người gọi chứ không phải bởi chính phương pháp đó? –

+0

Không chắc chắn tôi hoàn toàn nhận được quan điểm của bạn. Là một hack nhanh chóng tôi trả lại một Object từ khôi phục (..) và làm một kiểm tra instanceof ở một mức độ cao hơn, không có generics tham gia (vì họ không giúp anyways). Tuy nhiên, điều này là xấu xí. – yanchenko

3

Sẽ không có bất kỳ ClassCastException, trừ khi T của bạn có một số cơ sở:

public class GenericsTest 
{ 
    public static void main(String[] args) 
    { 
     System.out.println(cast(Integer.valueOf(0))); 
     System.out.println(GenericsTest.<Long> cast(Integer.valueOf(0))); 
     System.out.println(GenericsTest.<Long> cast("Hallo")); 

     System.out.println(castBaseNumber(Integer.valueOf(0))); 
     System.out.println(GenericsTest.<Long> castBaseNumber(Integer.valueOf(0))); 
     System.out.println(GenericsTest.<Long> castBaseNumber("Hallo")); 
    } 

    private static <T extends Number> T castBaseNumber(Object o) 
    { 
     T t = (T)o; 
     return t; 
    } 

    private static <T> T cast(Object o) 
    { 
     T t = (T)o; 
     return t; 
    } 
} 

Trong ví dụ trên, sẽ có không có ClassCastException trong 5 cuộc gọi đầu tiên để truyền và castBaseNumber. Chỉ có cuộc gọi thứ 6 ném một ClassCastException, bởi vì trình biên dịch dịch một cách hiệu quả hàm cast() để trả về (Object) o và hàm castBaseNumber() để trả về (Number) o ;. Wenn bạn viết

String s = GenericsTest.<Long> cast("Hallo"); 

Bạn sẽ nhận được một ClassCastException, nhưng không theo phương pháp truyền, nhưng tại thời điểm gán cho s.

Vì vậy, tôi nghĩ rằng, "T" của bạn không chỉ là "T", nhưng "T mở rộng một cái gì đó". Vì vậy, bạn có thể kiểm tra:

Object o = decoder.readObject(); 
if (o instanceof Something) 
    restoredItem = (T) o; 
else 
    // Error handling 

Nhưng điều này sẽ vẫn dẫn đến lỗi sau này khi bạn sử dụng lớp học.

public Reader<T extends Number>{...} 

Long l = new Reader<Long>("file.xml").getValue(); // there might be the ClassCastException 

Chỉ trong trường hợp này, tư vấn của Tom có ​​thể hữu ích.

0

Nếu bạn không thể sử dụng instaceof, bạn có thể sử dụng phương thức isAssignableFrom trên Class

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