2010-04-09 27 views
9

Tôi gặp sự cố khi biên dịch một lớp chung với lớp bên trong. Lớp mở rộng một lớp chung chung, lớp bên trong cũng có.Lỗi biên dịch thừa kế của lớp bên trong chung mở rộng với các giới hạn

đây giao diện thực hiện:

public interface IndexIterator<Element> 
    extends Iterator<Element> 
{ 
    ... 
} 

Các generic siêu lớp:

public abstract class CompoundCollection<Element, Part extends Collection<Element>> 
    implements Collection<Element> 
{ 
    ... 

    protected class CompoundIterator<Iter extends Iterator<Element>> 
     implements Iterator<Element> 
    { 
    ... 
    } 
} 

Các lớp con chung với lỗi biên dịch:

public class CompoundList<Element> 
    extends CompoundCollection<Element, List<Element>> 
    implements List<Element> 
{ 
    ... 

    private class CompoundIndexIterator 
     extends CompoundIterator<IndexIterator<Element>> 
     implements IndexIterator<Element> 
    { 
    ... 
    } 
} 

Lỗi này là:

type parameter diergo.collect.IndexIterator<Element> is not within its bound 
     extends CompoundIterator<IndexIterator<Element>> 
              ^

Điều gì là sai? Mã biên dịch với nhật thực, nhưng không phải với trình biên dịch java 5 (tôi sử dụng kiến ​​với java 5 trên mac và eclipse 3.5). Không, tôi không thể chuyển đổi nó thành một lớp bên trong tĩnh.

+1

Bất kỳ cơ hội nào bạn có thể thử bằng Java 6?Nó có thể là một lỗi trình biên dịch. –

+0

Chỉ cần thử với Java 6. Thông báo lỗi tương tự. Thú vị ... –

+0

@mmyers: ý tưởng tốt @Eval: cảm ơn, cũng đã thử bản thân mình trên máy Mac 1.6 jdk - lỗi tương tự –

Trả lời

8

Các Java Language Specification, §8.1.3, xác định ngữ nghĩa của subclassing loại bên trong như sau :

Furthermore, for every superclass S of C which is itself a direct inner class of a class SO, there is an instance of SO associated with i, known as the immediately enclosing instance of i with respect to S. The immediately enclosing instance of an object with respect to its class' direct superclass, if any, is determined when the superclass constructor is invoked via an explicit constructor invocation statement.

Lưu ý rằng các ví dụ kèm theo là chỉ được mô tả là có một lớp học đặc biệt , không phải là một đặc biệt loại. Như tất cả các trường của một loại cổ phiếu chung cùng lớp, các mã sau đây sẽ là quy phạm pháp luật:

class Base<E> { 
    E e; 

    protected class BaseInner<I extends E>{ 
     E e() { return e; } 
    } 
} 

class StrangeSub extends Base<Integer> { 
    protected class StrangeSubInner extends Base<String>.BaseInner<String> {} 
} 

Tất nhiên, điều này có thể được sử dụng để phá vỡ các loại bất biến (tức là nguyên nhân đống ô nhiễm):

StrangeSub ss = new StrangeSub(); 
    ss.e = 42; 
    String s = ss.new StrangeSubInner().e(); 

Trình dịch nhật thực lấy Đặc tả ngôn ngữ Java làm giá trị khuôn mặt và chấp nhận mã ở trên mà không phát ra cảnh báo "không được chọn". Trong khi được cho là tuân thủ về mặt kỹ thuật với JLS, điều này rõ ràng vi phạm ý định của nó.

Sun Java Compiler bác bỏ tuyên bố của StrangeSubInner với:

Test.java:32: type parameter java.lang.String is not within its bound 
     protected class StrangeSubInner extends Base<String>.BaseInner<String> {} 
                    ^

Rõ ràng trình biên dịch không chỉ đơn giản là kiểm tra các tham số kiểu chống tham số lớp loại siêu bên trong của ràng buộc như nhật thực đã làm. Trong trường hợp này, tôi tin rằng điều này là đúng đắn, vì tuyên bố rõ ràng là không an toàn. Tuy nhiên, trình biên dịch Sun đều bác bỏ lời tuyên bố sau đây, mặc dù nó là provably loại an toàn:

class StrangeSub extends Base<Integer> { 
    protected class StrangeSubInner extends BaseInner<Integer> {} 
} 

linh cảm của tôi là kiểm tra sự phù hợp của hình thoi hạn chế kiểu này là vượt quá khả năng của trình biên dịch Sun, và do đó, các cấu trúc như vậy được loại bỏ một cách tổng quát.

Để làm việc xung quanh giới hạn này, trước hết tôi muốn loại bỏ thông số loại thành CompoundIterator.

+0

Cảm ơn, vì vậy tôi cần thực hiện theo cách cũ - chỉ cần truyền (tên chung được sử dụng cho thành viên). –

+0

+1 Rất thú vị. –

1

Có lẽ đây không phải là có nhiều tiến bộ, nhưng tôi thành công rút ngắn mã ở trên để đoạn mã sau đó vẫn thể hiện những hành vi kỳ lạ như nhau:

class Base<E> { 
    protected class BaseInner<I extends E>{ 
    } 
} 

class Sub<E> extends Base<E>{ 
    class SubInner extends BaseInner<E> { 
    } 
} 
Các vấn đề liên quan