2011-01-11 14 views
5

sto usando Java 6.Java caso interruttore - Default vs esplicito l'enumerazione

Supponiamo che io ho un enum con 6 valori, ordinato dalla A alla F. Circa 4 dei valori sono stati trattati allo stesso. Potrei scrivere in questo modo.

switch (whichType) { 
    case A: 
    case B: 
    case C: 
    case D: 
     return task(); 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
} 

O come questo.

switch (whichType) { 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
    default: 
     return task(); 
} 

I valori nulli non raggiungeranno mai questo interruttore.

In termini di concisione e chiarezza, il secondo approccio è migliore. In termini di esplicitazione, penso che il primo approccio sia migliore.

Ci sono altri vantaggi/svantaggi di ogni approccio?

Inoltre, questa semplice domanda rischia di essere un duplicato, ma ho provato e non riuscivo a trovarlo chiesto da nessuna parte ancora. Mi scuso se non l'ho cercato abbastanza bene.

+4

aggiungere un metodo astratto alla classe enum? – Ron

+2

Solo per la cronaca: puoi _can_ mettere una sezione 'default' in alto, al centro, o in qualsiasi altra parte all'interno di' switch'; non deve essere in fondo. –

+0

@ ChrisJester-Young Ma alcuni analizzatori di codici statici vietano il posizionamento di default in posizioni non di fondo. – mjafari

risposta

7

Entrambi sono bene se questo è assolutamente enum, fissato positivamente a sei valori per sempre. Altrimenti, pensa a quale potrebbe essere un possibile settimo valore per l'enum. Se E e F sono gli unici due valori anomali possibili rispetto a questa logica switch e qualsiasi altro valore ricade nello stesso segmento da A a D, andare avanti e utilizzare default. Altrimenti, sei più sicuro di avere un case per valore.

3

Supponiamo che qualcuno aggiunga un valore all'enumerazione?

In un certo codice che ho, c'è questa sorta di costrutto:

switch(mediaType) { 
    case typeA: 
    case typeB: 
    case typeC: 
     DoGeneric(); 
     break; 
    case TypeD: 
     DoSpecial(); 
     break; 
} 

E la ragione di ciò è così che se qualcuno aggiunge un'altra possibilità per l'enumerazione, non verrà compilato fino a quando' Abbiamo esaminato i luoghi in cui è stata utilizzata l'enumerazione e abbiamo deciso cosa fare in quel momento. Nessuna possibilità di averne uno e di avere un bug difficile da rintracciare.

+0

+1 per il caso di aggiungere un nuovo elemento all'enumerazione. – unholysampler

+4

Ummm ... il codice ** verrà ** compilato dopo che qualcuno ha aggiunto 'typeE'. –

+0

@Stephen C: A seconda del linguaggio, sì potrebbe (non sviluppo in Java). In questo modo, gli strumenti di stile del codice possono captarlo, mentre con 'default' è impossibile sapere se è stato dimenticato o no. –

2

Beh, per quanto riguarda la leggibilità, direi che il secondo non può essere più chiaro. Ad esempio, il tuo caso comune accade DOPO i tuoi casi speciali.

Tuttavia, il vero problema che vedo qui è i due pezzi di codice non sono realmente equivalenti. Nel primo caso, hai sei casi espliciti. Nella seconda, hai due casi espliciti e un caso predefinito. Ciò significa che, se il tuo codice ha qualche tipo di errore nel caso in cui tu riceva un caso che non ti aspetti, il caso predefinito verrà comunque eseguito nel secondo (e verrà eseguito ancora task()). Di conseguenza, questo è fondamentalmente diverso dal tuo primo codice.

Diverso da quello (decidendo quale istruzione di commutazione è corretta), direi bastone con quello che legge il meglio per voi. Personalmente mi piace il primo (perché è esplicito e lascia spazio a un caso predefinito se ne è necessario uno), ma dovrai decidere in base alle tue preferenze o agli standard di sviluppo della tua azienda/squadra.

0

Se si sta scrivendo qualche scenario di business e si prevede che il codice venga mantenuto e mantenuto (da qualche altra persona) per gli anni a venire, andare con l'opzione 1. Non c'è niente di sbagliato nell'opzione 2, è breve e chiaro, ma quando si parla di manutenibilità, penso che l'opzione 1 vince, specialmente se i casi sono legati ad alcune logiche di business. Sarà molto più facile per il tecnico di manutenzione leggerlo.

2

Io tendo a utilizzare predefinito per acquisire nuove enumerazioni aggiunte dopo l'implementazione iniziale. Questo non produce un errore in fase di compilazione, che preferirei, ma generalmente non supera i test sul fumo.

switch (whichType) { 
    case A: 
    case B: 
    case C: 
    case D: 
     return task(); 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
    default: 
     throw new IllegalArgumentException("Encountered unknown type: " + whichType.name()); 
}