2012-05-28 19 views
16

Oto prosty przykład z jakiegoś kodu, który kompiluje używając Java 6, ale nie skompilować w Javie 7.Zmiany w dostępie do zmiennych klas rodzajowych w Javie 7

public class Test<T extends Test> { 

    private final int _myVar; 

    public Test(int myVar) { 
    _myVar = myVar; 
    } 

    public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return t._myVar; 
    } 

    private static class TestContainer<T extends Test> { 
    private final T _test; 
    private TestContainer(T test) { 
     _test = test; 
    } 
    public T get(){ 
     return _test; 
    } 
    } 
} 

W Javie 7, to nie kompilacji w metodzie get(TestContainer<T> container), z błędem:

error: _myVar has private access in Test

ja nie rozumiem, dlaczego to nie kompiluje - w moim umyśle powinien. Zmienna t jest typu T, która musi rozciągać się na Test. Próbuje uzyskać dostęp do pola _myVar instancji Test z klasy Test.

Rzeczywiście, jeśli mogę zmienić metodę get(TestContainer<T> container) do dalszej kompiluje (bez ostrzeżenia):

public int get(TestContainer<T> container){ 
    Test t = container.get(); 
    return t._myVar; 
} 
  • Dlaczego to nie skompilować?
  • Czy to błąd w Java 6? Jeśli tak, dlaczego?
  • Czy to błąd w Java 7? Komentarz

miałem google i wyszukuje w bazie danych Oracle błędów, ale nie znalazłem nic na ten temat ...

+5

To był błąd w Javie 6: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7022052 – pingw33n

+0

@ pingw33n, należy zakładać, że jako odpowiedź. –

+0

@ pingw33n, a następnie mogę go zaakceptować ... chociaż jeśli ktoś, kto lepiej zrozumie JLS, może wyjaśnić sekcję "Ocena" w raporcie o błędzie, również bym to docenił. – amaidment

Odpowiedz

9

§4.9 ... Then the intersection type has the same members as a class type (§8) with an empty body, direct superclass Ck and direct superinterfaces T1', ..., Tn', declared in the same package in which the intersection type appears.

Z mojego zrozumienia tego JLS strony, sprawa z typem zmiennej <T extends Test> tworzy następujące skrzyżowania:

package <the same as of Test>; 

class I extends Test {} 

Dlatego, gdy masz dostęp do członków rodzaju T rzeczywiście dostęp członków skrzyżowaniu typ I. Ponieważ członkowie prywatni nigdy nie są dziedziczeni przez podtypy, dostęp do takiego elementu kończy się błędem kompilacji. Z drugiej dostępu rękę do opakowania-prywatnego (domyślnie) i członków chronionych jest dozwolona przez fakt przecięcia jest

... declared in the same package in which the intersection type appears.

0

See @ pingw33n za odpowiedź, ale sposób, aby rozwiązać ten problem jest aby usunąć ogólne parametry w klasie zagnieżdżonej. Jeśli nie masz przypadku użycia, w którym wewnętrzna i zewnętrzna literka T mogą być różne, są zbędne. Wszystko, co robią, powoduje ten smutek.

+0

Sugerujesz, aby po prostu: 'private static class TestContainer'? Od klasy wewnętrznej statycznej, nie możesz (w słownych słowach kompilatora) * utworzyć statyczne odwołanie do typu niestacjonarnego T *. –

+0

Mam przypadek użycia - odpowiednik TestContainer jest w rzeczywistości całkowicie oddzielną klasą - ale to tylko SSCCE, aby zademonstrować problem kompilatora, z którym miałem do czynienia. – amaidment

0

Rozwiązaniem jest do oddania instancję rodzajowego do betonowego supertypem który deklaruje pola prywatnego, na przykład

public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return ((Test) t)._myVar; 
} 
Powiązane problemy