2011-01-28 35 views
23

Có một số câu hỏi SO khác nói về generics biên dịch OK w/trình biên dịch của Eclipse nhưng không phải javac (tức là Java: Generics handled differenlty in Eclipse and javacGenerics compiles and runs in Eclipse, but doesn't compile in javac) - tuy nhiên điều này có vẻ hơi khác một chút.lỗi javac: các loại không thể thay đổi với generics?

Tôi có một lớp enum:

public class LogEvent { 
    public enum Type { 
     // ... values here ... 
    } 
    ... 
} 

và tôi có một lớp học với một phương pháp mà mất trong đối tượng tùy tiện của các loại có nguồn gốc từ Enum:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{ 
    if (code instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)code; 
    ... 

này hoạt động tốt trong Eclipse, nhưng khi tôi làm sạch được xây dựng với ant, tôi gặp phải một số lỗi, một lỗi trên đường dây instanceof, số còn lại trên đường truyền:

443: inconvertible types 
    [javac] found : E 
    [javac] required: mypackage.LogEvent.Type 
    [javac]   if (code instanceof LogEvent.Type) 
    [javac]   ^

445: inconvertible types 
    [javac] found : E 
    [javac] required: com.dekaresearch.tools.espdf.LogEvent.Type 
    [javac]    LogEvent.Type scode = (LogEvent.Type)code; 
    [javac]            ^

Tại sao điều này xảy ra và làm cách nào tôi có thể khắc phục vấn đề này để nó có thể biên dịch đúng cách?

Trả lời

32

Tôi không biết tại sao nó đang xảy ra, nhưng một workaround là dễ dàng:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{ 
    Object tmp = code; 
    if (tmp instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)tmp; 
    ... 

Nó xấu xí, nhưng nó hoạt động ...

+0

cảm ơn. Tại sao điều đó xấu xí? Nó đơn giản và có chi phí thời gian chạy thấp. –

+3

@ Jason S: Thật xấu vì tôi không thể thấy lý do tại sao nó được yêu cầu. –

+0

Đây là lỗi đã biết, IIRC. Trên thực tế, có hàng tá lỗi liên quan mà không có lỗi nào trong số chúng được khắc phục. – maaartinus

0

Để sử dụng instanceof cả hai toán hạng đã kế thừa/thực hiện cùng một lớp/giao diện.
E không thể truyền sang LogEvent.Type

Tôi không biết phương thức đầy đủ của bạn trông như thế nào, nhưng điều này sẽ giải quyết vấn đề của bạn bằng cách sử dụng giao diện chứ không phải Generics.

public interface EventType { } 
public class LogEvent { 
    public enum Type implements EventType {} 
} 

public void postEvent(Context context, EventType code, Object additionalData) { 
    if(code instanceof LogEvent.Type) { 
    } 
} 
+0

Nhưng tôi muốn Enum là loại cơ sở chứ không phải EventType. Tôi cần phương pháp của tôi để chấp nhận các giá trị Enum tùy ý. –

+0

Nhưng tại sao E không thể chuyển sang LogEvent.Type? E là một lớp con của Enum, và LogEvent.Type cũng là một lớp con của Enum. Tôi hiểu rằng phần vấn đề là nó không chỉ là Enum, nhưng Enum , tôi chỉ không thể hiểu điều đó có nghĩa là chính xác. –

+0

Các câu hỏi SO khác về chủ đề này dường như chỉ ra rằng 'javac' có lỗi đã biết với các giới hạn chung đệ quy, vì vậy có thể nó bị nhầm lẫn. Đối với '>', nếu bạn chưa từng thấy nó trước đây: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106 –

8

Có lẽ đó là vì bạn đã tuyên bố E như một cái gì đó mà kéo dài Enum <E>. Tôi không thể nói tôi hiểu nó hoàn toàn, nhưng có vẻ như nó giới hạn tập hợp các loại cho một số tập con mà không thể bao gồm LogEvent.Type vì một số lý do. Hoặc có thể nó chỉ là một lỗi trong trình biên dịch. Tôi sẽ rất vui nếu ai đó có thể giải thích rõ ràng hơn, nhưng dưới đây là những gì bạn có thể làm:

public <E extends Enum<?>> void postEvent(E code) 
{ 
    if (code instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)code; 
     ... 
    } 
    ... 

Công trình này và thanh lịch hơn là chỉ đúc cho Vật thể.

+1

nó hoạt động vì "E mở rộng Enum "đề cập đến một số lớp con cụ thể của Enum (có thể không tương thích với LogEvent.Type). trong khi "E mở rộng Enum " dùng để chỉ bất kỳ lớp nào mở rộng Enum, trong đó LogEvent.Type là một khả năng hợp lệ. – jtahlborn

+0

@jtahlborn: Các 'E mở rộng Enum ' là tiêu chuẩn boilerplate cho bất kỳ lớp học mà mở rộng đúng Enum, mà tất cả các lớp 'enum' làm, và' LogEvent.Type' là một lớp 'enum', do đó, nó sẽ làm việc là tốt, nhưng có vẻ như là một lỗi trong 'javac'. –

+0

@jtahlborn, vâng, nghĩ về nó - LogEvent.Type có mở rộng Enum không? Chắc chắn là vậy. Nhưng đó là chính xác những gì chúng tôi có nghĩa là khi chúng tôi viết "E mở rộng Enum ", với E = LogEvent.Type. Vì vậy, tôi đồng ý rằng nó trông giống như một lỗi trong javac. Trong thực tế, "E mở rộng Enum " và "E mở rộng Enum " nên có nghĩa là chính xác điều tương tự vì bất kỳ loại enum E chỉ có thể mở rộng Enum và không có gì khác. –

4

Tôi đã gặp sự cố tương tự và được nâng cấp từ jdk1.6.0_16 lên jdk1.6.0_23 và nó biến mất mà không có bất kỳ thay đổi mã nào.

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