2009-10-02 16 views
15

Ho tre tipi Java come definito di seguito:javac si lamenta: non riesce a trovare il simbolo sul enum attuazione interfaccia

Main.java:

import java.util.Arrays; 
import java.util.List; 

public class Main 
{ 
    private Object callFunction() 
    { 
     OperationDefinitions func = OperationDefinitions.CONCATENATE; 
     List<Object> values = Arrays.asList(new Object[] {"ABC", "-", "DEF"}); 
     return func.call (values); 
    } 

    public static void main (String[] args) 
    { 
     Main main = new Main(); 
     System.out.println (main.callFunction()); 
    } 
} 

Operation.java

import java.util.List; 

public interface Operation 
{ 
    abstract Object call(List<Object> params); 
} 

OperationDefinitions.java

import java.util.List; 

enum OperationDefinitions implements Operation 
{ 
    CONCATENATE() { 
     public Object call(List<Object> params) 
     { 
      StringBuilder builder = new StringBuilder(); 
      for (Object param : params) builder.append((String)param); 
      return builder.toString(); 
     } 
    }, 
    ; 

} 

(Questo è quasi esattamente l'esempio fornito in Efficace Java 2nd ed. Articolo 30) Il codice sopra compila e funziona bene in Eclipse, ma con Sun javac ottengo il seguente errore:

Main.java:12: cannot find symbol 
symbol : method call(java.util.List<java.lang.Object>) 
location: class OperationDefinitions 
     return func.call (values); 
         ^
1 error 

Se cambio linea 12 di Main.java da return func.call(values); a return ((Operation)func).call(values) si compila bene. Inoltre, se metto insieme i tre tipi (Operation, Main e OperationDefinitions) come tre sottoclassi di una singola classe principale, compila bene.

Quindi ho soluzioni alternative per il mio problema, ma mi chiedo, perché javac richiede un cast qui, ma eclipse no? Si tratta di un bug in javac o in eclissi?

Ho provato sia Sun javac 1.5.0_19 e 1.6.0_16

risposta

10

Potrebbe essere un bug nel javac del sole. func è un enum (anche se quello implementa Operation) e la classe Enum non ha un metodo call(). Per risolvere il problema, suggerisco di modificare l'assegnazione:

Operation func = OperationDefinitions.CONCATENATE; 

che sarà anche mettere in chiaro quello che ci si aspetta: Un'operazione, non un enum. Il enum è solo un modo conveniente per raccogliere tutte le operazioni possibili (un contenitore se lo si desidera).

+2

+1 per lo stile, normalmente quella sarebbe la cosa giusta da fare. Quello che non ho spiegato qui è che questo è solo un piccolo frammento del codice reale, e OperationDefinitions ha funzioni membro aggiuntive che non sono in Operation, come getHelp() e getDescription() – amarillion

+0

Senza contare che dovremmo sempre programmare interfacce non classi! getHelp e getDesctiption dovrebbero essere definiti in un'altra interfaccia. Supponiamo che tu abbia un'interfaccia come l'interfaccia Helper {String getHelp(); String getDescription();} Quindi è possibile richiamare getHelp() come segue: Helper helper = OperationDefinitions.CONCATENATE; helper.getHelp(); – uthomas

0

Sospetto che si tratti di un bug in javac; OperationDefinitions sicuramente fa ha una chiamata al metodo (abstract) (java.util.List), poiché implementa l'interfaccia Operation. E la definizione della classe è valida, poiché tutte le costanti forniscono un'implementazione concreta di questa interfaccia.

Una cosa che potrebbe essere parzialmente responsabile di questo è che, per quanto ne so, tutti i metodi definiti in un'interfaccia devono essere pubblici. Se hai veramente definito il metodo call nell'interfaccia con il modificatore di accesso predefinito, mi aspetterei che il compilatore lo rifiutasse, ma se non lo fa, non mi sorprenderebbe vedere i problemi lungo la linea. Se questo è un errore allora va bene, ma se è così nel tuo codice prova a dichiararlo come pubblico e verifica se il problema scompare.

+4

Tutti i metodi nell'interfaccia sono implicitamente astratti e pubblici. Se ometti quei modificatori (che è raccomandato da AFAIK), il compilatore li aggiungerà per te. Se scrivi qualche altro modificatore, riceverai un errore. –

2

Questo è un bug, come ci ha indicato "Stephen Denne", ma se non è possibile eseguire l'aggiornamento a una nuova versione (ma dovrebbe) ...Basta togliere l'inteface da OperationDefinitions e mettere il metodo ...call(...) al enum, in questo modo:

public abstract Object call(List params);

dovrebbe funzionare.

Problemi correlati