2012-05-28 16 views
16

Ecco un semplice esempio di codice che compila utilizzando Java 6, ma non viene compilato in Java 7.Le variazioni di accesso di variabili per le classi generiche in Java 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; 
    } 
    } 
} 

In Java 7, non riesce a compilo nel metodo get(TestContainer<T> container), con l'errore:

error: _myVar has private access in Test

non capisco il motivo per cui questo non è più compila - nella mia mente dovrebbe. La variabile t è di tipo T, che deve estendere Test. Sta tentando di accedere al campo _myVar di un'istanza di Test all'interno della classe Test.

Anzi, se cambio il metodo get(TestContainer<T> container) al seguente, compila (senza avvisi):

public int get(TestContainer<T> container){ 
    Test t = container.get(); 
    return t._myVar; 
} 
  • Perché questa compilazione non è più?
  • Si trattava di un bug in Java 6? Se è così, perché?
  • Si tratta di un bug in Java 7? commento

Ho avuto un google e cercare nel database dei bug di Oracle, ma non ho trovato nulla su questo ...

+5

Questo era un bug in Java 6: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7022052 – pingw33n

+0

@ pingw33n, si dovrebbe post che come una risposta. –

+0

@ pingw33n, e quindi posso accettarlo ... anche se chiunque abbia una migliore comprensione del JLS può spiegare la sezione "Valutazione" del bug report, lo apprezzerei anche io. – amaidment

risposta

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.

Dalla mia comprensione di quella parte JLS, il tuo caso con un tipo di variabile <T extends Test> crea il seguente incrocio:

package <the same as of Test>; 

class I extends Test {} 

Pertanto quando si accede membri del tipo T effettivamente accedere membri della intersezione digitare I. Poiché i membri privati ​​non vengono mai ereditati da sottotipi, l'accesso a tale membro fallisce con l'errore di compilazione. D'altro canto, i pacchetti-privato (default) e membri protetti è consentito dal fatto intersezione è

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

0

vedere @ di pingw33n per la risposta, ma il modo per risolvere questo problema è rimuovere i parametri generici nella classe nidificata. A meno che tu non abbia un caso d'uso in cui le T interne ed esterne possono essere diverse, sono ridondanti. Tutto quello che stanno facendo è causare questo dolore.

+0

Stai suggerendo di farlo semplicemente: 'testContainer di classe statica privata'? Dal momento che la classe interna statica, non è possibile (nelle parole terse del compilatore) * fare un riferimento statico al tipo non statico T *. –

+0

Ho un caso d'uso - l'equivalente di TestContainer è in realtà una classe separata interamente - ma questo è solo un SSCCE per dimostrare il problema del compilatore che stavo affrontando. – amaidment

0

Una soluzione per questo è di lanciare l'istanza generica al supertipo concreto che dichiara il campo privato, per esempio

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