2012-07-24 11 views
5

EDIT: ho cambiato un po 'l'esempio per ottenere l'idea:C'è un modo di imitare O in Java Generics

Come

<Integer or Float> 

... senza dover creare un'interfaccia comune e fare una sottoclasse per Integer e Float per la sua attuazione

in caso contrario, qualcosa di simile sarebbe forse ha più senso ed essere utile

<E extends Number> <E = (Integer|Float)> 

Se? è un carattere jolly perché non dovremmo permetterci di limitare determinati tipi?

+1

perché vuoi farlo? – Pshemo

+0

Sembrano gesso e formaggio. Il requisito non ha alcun senso per me. Le stringhe sono entità matematiche come i numeri, chiuse su determinate operazioni? Non pensavo – duffymo

+0

Proprio perché String è definitivo, una soluzione o sarebbe necessaria ancora di più, perché non potremmo risolverlo con l'alternativa che propongo. – Whimusical

risposta

10

Non è possibile e difficilmente vedo alcun valore. Usi i generici per limitare il tipo, ad es. in collezioni. Con l'operatore or tu sai tanto del tipo quanto sai del supertipo più specifico di entrambi, Object in questo caso. Allora perché non usare solo Object?

ipotetico:

List<E extends String or Number> list = //... 

Qual è il tipo di list.get(0)? È StringoNumber? Ma non puoi avere una variabile di questo tipo. Non può essere String, non può essere Number - può essere solo ... Object.

UPDATE: Dal momento che hai cambiato il tuo esempio in questione:

<Integer or Float> 

perché non ti basta dire:

<Number> 

? Notare che Number ha metodi che consentono di estrarre facilmente floatValue() e intValue(). Hai davvero bisogno del tipo esatto?


Si noti che è possibile utilizzare and operatore:

<E extends Serializable & Closeable> 

E che rende perfettamente senso - è possibile utilizzare variabile di tipo E in cui o è necessario Serializable o Closeable. In altre parole, E deve estendere sia Serializable sia Closeable. Vedi anche: Java Generics Wildcarding With Multiple Classes.

+0

Ok per la lista è stupido, ma per altri usi potrebbe non essere così. Anche tu potresti avere una stringa a = list.get (0) o un intero a = list.get (0), brutto ma non impossibile o impraticabile. Potrebbe lanciare un CastExeption se l'errore – Whimusical

+2

@ user1352530: evitare 'ClassCastException' e compilare il controllo del tipo di tempo è stato uno dei motivi per includere i generici in primo luogo. –

+0

Ho aggiornato la domanda con un nuovo approah che rende lo stesso per me – Whimusical

1

non vedo un vero e proprio uso per esso ... Ma in ogni modo, credo che il più vicino si otterrebbe ad esso sta estendendo le interfacce comuni per i possibili implementazioni.

5

In casi estremi (pre-Java 7 senza AutoCloseable), avrei voluto poterlo fare anche io. Per esempio.

<E extends Connection or Statement or ResultSet> 

Che avrebbe mai permesso di chiamare E.close(), non importa quale sia il tipo effettivo era. In altre parole, E conterrà "l'intersezione API" di tutti i tipi forniti.In questo caso conterrà close() e tutti i metodi da java.sql.Wrapper e java.lang.Object.

Ma sfortunatamente, non puoi farlo. Invece, usa l'overloading del metodo, ad es.

void close(Connection c); 
void close(Statement s); 
void close(ResultSet r); 

O pianura vecchio instanceof

if (obj instanceof Connection) { 
    ((Connection) obj).close(); 
} 
else if (obj instanceof Statement) { //... 

o correggere il vostro disegno, come probabilmente non dovrebbe avere intersecare le API di tipi arbitrari comunque

+1

In Java 7 tutte queste classi implementano ['AutoCloseable'] (http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html) così" "è ora abbastanza. –

+0

''? – GriffeyDog

+0

@TomaszNurkiewicz: lo so. È solo un'illustrazione. @GriffeyDog: vedi la risposta di Tomasz. I tipi JDBC estendono 'AutoCloseable', non' Closeable' (che estende anche 'AutoCloseable') –