2010-11-10 34 views
6

Chúng tôi có một hệ thống phân cấp lớp tương tự như thế này:Sun JDK 1.5 có thể không dereference lỗi với Generics

public class TestDereference { 
private static MainInterface mi = new MainInterfaceImpl(); 

public static void main(String[] args) { 
    System.out.println(mi.getSubInterface().getField()); 
} 
} 

interface MainInterface { 
<T extends SubInterface> T getSubInterface(); 
} 

interface SubInterface { 
Field getField(); 
} 

class Field { 
@Override 
public String toString() { 
    return "Hooray!"; 
} 
} 

class SubInterfaceImpl implements SubInterface { 
Field f = new Field(); 

public Field getField() { 
    return f; 
} 

} 

class MainInterfaceImpl implements MainInterface { 
SubInterfaceImpl si = new SubInterfaceImpl(); 

public <T extends SubInterface> T getSubInterface() { 
    return (T) si; 
} 
} 

Các giao diện thực sự có nhiều hơn một thực hiện nhưng đó không phải là vấn đề. Biên dịch điều này với trình biên dịch Eclipse hoặc Java 1.6 hoạt động tốt (như đã thấy trên ideone). Nhưng nếu tôi cố gắng biên dịch này với Java 1.5 (mà là một trong những yêu cầu của dự án của chúng tôi) cung cấp cho các lỗi sau:

TestDereference.java:12: test.SubInterface cannot be dereferenced 
       System.out.println(mi.getSubInterface().getField()); 
                ^

Cũng lưu ý rằng nó không xảy ra với JDK 1.6 sử dụng -target 1.5 một trong hai, chỉ với JDK 1.5

các trường hợp chỉ khi lỗi này xảy ra mà tôi tìm thấy trên web có liên quan đến làm việc như thế này:

double d = 2.0; 
d.toString(); 

nơi nó rõ ràng vấn đề là gì.

Nhưng trường hợp của tôi sẽ hoạt động, vì rõ ràng là getSubInterface() trả về một lớp thực hiện SubInterface chắc chắn có phương thức getField().

Vì vậy, đây có phải là lỗi trình biên dịch không? Và những tùy chọn nào tôi có bên cạnh việc làm mi.<SubInterface>getSubInterface() mỗi lần duy nhất (hoạt động, nhưng vì Eclipse không đánh dấu đây là lỗi, hầu hết mọi người trong nhóm quên làm điều đó, và hầu hết trong số họ chỉ sử dụng JDK 1.6 để họ không chú ý khi biên dịch với dòng maven/cmd)?

+0

gì phiên bản của JDK chính xác mà bạn đang sử dụng? (5 và 6?) –

+0

1.5.0_22 và 1.6.0_20 (theo 'javac -version') –

+0

Điều gì xảy ra khi bạn thử cờ trình biên dịch' -source 1.5' hoặc nếu bạn đặt mức tuân thủ Trình biên dịch Eclipse thành 1.5 thay vì 1.6? –

Trả lời

1

Kiểm tra lỗi: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5003431

Lựa chọn một:

SubInterface si = mi.getSubInterface(); 
si.getField(); 

Lựa chọn hai:

mi.<SubInterface>getSubInterface().getField() 
+0

Vì vậy, tôi đoán nếu tôi bị mắc kẹt với 1.5 không có nhiều tôi có thể làm ngoài hai tùy chọn này. Tôi đã hy vọng cho một cái gì đó một chút tao nhã hơn tôi đoán, nhưng điều này sẽ phải làm. –

+0

Tôi chấp nhận câu trả lời của bạn cũng cho liên kết đến báo cáo lỗi, cho thấy nó chỉ được sửa trong 1.6 –

1

Tôi đoán đây là lỗi đã được sửa trong Java6.

Viết lại phương pháp chính của bạn như sau sẽ làm cho mọi việc trong cả hai Java5 và 6:

public static void main(String[] args) { 
    SubInterface subInterface = mi.getSubInterface(); 
    System.out.println(subInterface.getField()); 
} 

Dường Java5 cần sự phân công để lấy được đúng loại T, mặc dù nó đã được công bố để mở rộng SubInterface. Java6 xử lý chính xác và không cần bổ sung.

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