2011-10-18 7 views
10

Ho un enum con un enum annidato (che voglio rendere privato), ma quando lo faccio GWT mi dice che l'enumerazione annidata non è visibile e genera un'eccezione.Utilizzo di enum annidato in GWT-RPC

public enum OuterEnum { 
    A(NestedEnum.X), 
    B(NestedEnum.Y), 
    C(NestedEnum.X); 

    NestedEnum nestedValue; 
    private OuterEnum(NestedEnum nv) { nestedValue = nv; } 

    private enum NestedEnum { 
     X, Y; 
    } 
} 

Se rimuovo il modificatore privato dall'enumerazione nidificata, il codice funziona. Perché GWT non consente il modificatore privato per enumerazioni annidate? C'è una soluzione?

+2

Hai provato a renderlo statico? –

+0

Questo è davvero fantastico! La JLS (sezione 8.9) dice esplicitamente che "i tipi di enumerazione annidata sono implicitamente statici ed è possibile dichiarare esplicitamente un tipo enum annidato come statico". Non si applica a 'enum's nidificato in' enum's o è un difetto secondario nel compilatore GWT? Il compilatore –

+0

... e GWT utilizza semplicemente il compilatore Eclipse (ECJ) per analizzare il codice sorgente e creare AST. Quindi, il compilatore Eclipse ha un bug nel non mostrare l'enum come statico, o GWT ha un bug nel non inferire il flag statico per un enum annidato (vorrei andare per ECJ, ma in realtà dipende dal loro intento; potrebbe essere by-design). –

risposta

2

La serializzazione funziona bene, almeno con l'esempio che hai fornito. Tutto enumerazioni un ottenendo serializzato/deserializzato in modo seguente (GWT 2.4, 2.3, 2.2):

public static OuterEnum instantiate(SerializationStreamReader streamReader) throws SerializationException { 
      int ordinal = streamReader.readInt(); 
      OuterEnum[] values = OuterEnum.values(); 
      assert (ordinal >= 0 && ordinal < values.length); 
      return values[ordinal]; 
} 

    public static void serialize(SerializationStreamWriter streamWriter, OuterEnum instance) throws SerializationException { 
      assert (instance != null); 
      streamWriter.writeInt(instance.ordinal()); 
} 

Ad es non importa cosa viene usato dentro Solo l'ordinale viene passato sulla rete. Significa che c'è un problema in qualche altro posto, GWT semplicemente non si cura di cosa c'è dentro enum, perché non è trasferito attraverso la rete (enum dovrebbe essere immutabile non c'è bisogno di trasferire il suo stato). Penso che il tuo problema potrebbe essere qualcosa del genere:

public class OuterClass implements Serializable{ 

    private OuterEnum.NestedEnum nested; 
    private OuterEnum outer; 

    public enum OuterEnum { 
     A(NestedEnum.X), B(NestedEnum.Y), C(NestedEnum.X); 

     NestedEnum nestedValue; 

     private OuterEnum(NestedEnum nv) { 
      nestedValue = nv; 
     } 


     private enum NestedEnum { 
      X, Y; 
     } 
    } 
} 

Questo esempio è MOLTO diverso dal precedente. Supponiamo che OuterClass sia utilizzato nel servizio GWT-RPC. Poiché NestedEnum è utilizzato come campo di OuterClass, GWT deve creare un TypeSerializer per esso. Ma dal momento che un TypeSerializer è una classe separata, non ha QUALSIASI accesso a NestedEnum (dato che è privato). Quindi la compilazione fallisce.

Questo in pratica è l'unico caso in cui il tuo esempio non funzionerà. Potrebbero esserci alcuni bug in alcune versioni GWT specifiche, ma sono sicuro al 100% che il tuo esempio funzioni in gwt 2.2-2.4.

0

Questo probabilmente ha a che fare con JavaScript. È possibile/probabile che nella traduzione in JavaScript la classe nidificata venga scritta come non annidata. Pertanto se è privato, nient'altro ha accesso ad esso. La soluzione alternativa è di non renderlo privato, l'ambito predefinito dovrebbe funzionare correttamente.

+0

Questo è un buon punto, non ci avevo pensato: idealmente mi piacerebbe che fosse privato ... – luketorjussen

-2

Per essere un tipo di classe parametro RPC, deve avere un costruttore vuoto per la serializzazione. Quindi penso, se si aggiunge

private OuterEnum(){ 
// may be you should give a default value to nestedValue 
} 

Funzionerà!

+0

Il problema è con la visibilità dell'enum interno. Può serializzare l'enum esterno bene, questo non risponde alla mia domanda – luketorjussen