2009-04-21 13 views
5

I nomi local classes vengono utilizzati molto raramente, in genere le classi locali sono anonime. Qualcuno sa perché il codice sottostante genera un avvertimento del compilatore?Java: classe locale e generici, perché avvisare il compilatore?

public class Stuff<E> { 
    Iterator<E> foo() { 
    class InIterator implements Iterator<E> { 
     @Override public boolean hasNext() { return false; } 
     @Override public E next() { return null; } 
     @Override public void remove() { } 
    } 
    return new InIterator(); 
    } 
} 

L'avviso è in new InIterator() e dice

[unchecked] unchecked conversion 
found : InIterator 
required: java.util.Iterator<E> 

Se la classe, invariata, è in forma anonima, o se si è fatto un membro, l'avviso va via. Tuttavia, come classe locale con nome, richiede una dichiarazione class InIterator<E> implements ... per l'avviso di andare via.

Cosa sta succedendo?

+0

Solo per curiosità, il mio compilatore non si lamenta di questo avviso ... Che JVM stai usando? –

+0

Aggiornamento Sun Java 6 12 – Yardena

risposta

1

Ora sono convinto che si tratti di un bug javac. Le soluzioni precedenti che aggiungono un parametro generico a InIterator che nasconde o sostituisce E non sono utili, perché precludono l'iteratore dal fare qualcosa di utile, come restituire un elemento di tipo E - Stuff's E.

Tuttavia questo compila con nessun avviso (grazie Jorn per il suggerimento):

public class Stuff<E> { 
    E bar; 
    Iterator<E> foo() { 
    class InIterator<Z> implements Iterator<E> { 
     @Override public boolean hasNext() { return false; } 
     @Override public E next() { return bar; } 
     @Override public void remove() { } 
    } 
    return new InIterator<Void>(); 
    } 
} 

Sicuramente un bug.

+0

Puoi segnalare un bug e pubblicare il link? Mi hai fatto incuriosire. –

+0

bene, secondo tweakt qui sotto non ci sono avvisi nell'aggiornamento 13. Controllerò, ma supponendo che abbia ragione, significa che è stato un errore :-) – Yardena

+0

Ah, ok. Hai controllato per vedere se è nella lista dei bug da qualche parte? –

3

Credo che stia accadendo ignorando l'argomento di tipo generico nominando InIterator senza un riferimento al generico nella firma (anche se è presente nell'interfaccia).

Questo rientra nella categoria degli avvisi di compilatore stupidi: hai scritto la classe in modo che il 100% delle istanze InIterator implementa Iterator<E>, ma il compilatore non lo riconosce. (Suppongo che questo dipenda dal compilatore Non vedo l'avviso nel mio compilatore Eclipse, ma so che il compilatore Eclipse gestisce i generici in modo leggermente diverso dal compilatore JDK.)

Io sostengo che questo è meno chiaro, e meno vicino a quello che vuoi dire, ma forse più compilatore amichevole, e, infine, equivalente:

public class Stuff<E> { 
    Iterator<E> foo() { 
    class InIterator<F> implements Iterator<F> { 
     @Override public boolean hasNext() { return false; } 
     @Override public E next() { return null; } 
     @Override public void remove() { } 
    } 
    return new InIterator<E>(); 
    } 
} 
+0

Grazie David. IntelliJ IDEA inoltre non ha mostrato alcun avviso, solo Sun javac. So come risolvere questo problema, mi sto semplicemente chiedendo se c'è qualche strana ma legittima ragione per questo comportamento del compilatore, o è un bug. – Yardena

+0

Ah, differenze di compilatore tra IDE e javac ... quanto fastidioso :( – Jorn

+0

Non è del tutto chiaro per me se si tratta di un bug che InIterator non è un Iterator o che InIterator implementa Iterator . –

1

Hmm, nessun avviso qui.

import java.util.Iterator; 

public class Stuff<E> { 
    Iterator<E> foo() { 
     class InIterator implements Iterator<E> { 
      public boolean hasNext() { 
       return false; 
      } 

      public E next() { 
       return null; 
      } 

      public void remove() { 
      } 
     } 
     return new InIterator(); 
    } 

    public static void main(String[] args) { 
     Iterator<String> i = new Stuff<String>().foo(); 
    } 
} 
+0

Hm, quale compilatore stai usando? – Yardena

+0

Testato all'interno di Eclipse (3.4), così come con Sun JDK 1.5.0.18 e 1.6.0.13 –

+0

c'è un avviso per Sun 1.6.0_11 e 1.6.0_12, controllerò 13, grazie! – Yardena

1

Sì, sono anche d'accordo che questo dovrebbe essere un bug. Se si "solleva" la classe locale dal metodo in una classe membro, funziona anche bene. E non c'è molta differenza tra i due eccetto diversi ambiti e accesso alle variabili locali.

public class Stuff<E> { 
    class InIterator implements Iterator<E> { 
    @Override public boolean hasNext() { return false; } 
    @Override public E next() { return null; } 
    @Override public void remove() { } 
    } 
    Iterator<E> foo() { 
    return new InIterator(); 
    } 
} 
Problemi correlati