2009-07-13 19 views
17

In Java, è possibile dichiarare un campo/variabile il cui tipo è costituito da più interfacce? Ad esempio, ho bisogno di dichiarare un Map che è anche Serializable. Voglio assicurarmi che la variabile faccia riferimento a una mappa serializzabile. L'interfaccia Map non si estende a Serializable, ma la maggior parte delle implementazioni di Map sono Serializable.Java, dichiarare la variabile con più interfacce?

Sono quasi sicuro che la risposta è no.

Follow-up: Sono pienamente consapevole della creazione di una nuova interfaccia che si estende sia Map e Serializable. Ciò non funzionerà in quanto le implementazioni esistenti (come HashMap) non implementano la mia nuova interfaccia.

risposta

7

Non è necessario dichiarare il campo/variabile come quello. Soprattutto perché può essere testato solo in fase di esecuzione e non in fase di compilazione. Crea un setter e segnala un errore se la Mappa passata non implementa Serializable.

Le risposte che consigliano di creare la propria interfaccia non sono ovviamente molto pratiche in quanto proibiscono attivamente l'invio di elementi che sono Maps e Serializable ma non l'interfaccia speciale.

+0

Anche se 'Map' implementa' Serializable', non significa necessariamente che sia serializzabile. Ma sì, la serializzazione Java è un problema di runtime in Java. –

+0

Sfortunatamente per Java, questa è la risposta giusta e merita di essere al top. – hythlodayr

+0

Ti sei perso la parte importante della mia risposta ... Accetti la Mappa e POI verifica se l'oggetto è un'istanza di Serializable. Ovviamente puoi farlo al contrario, ma otterrai un'interfaccia che non dice realmente all'utente quale tipo di raccolta desideri. – Fredrik

6
public interface MyMap extends Map, Serializable { 
} 

sarà definire una nuova interfaccia che è l'unione di Map e Serializable.

È, ovviamente, deve quindi fornire un adeguato attuazione del presente (per esempio MyMapImpl) e si può quindi fornire i riferimenti variabile del tipo MyMap (o Map o Serializable, a seconda delle esigenze).

Per chiarire il problema, non è possibile aggiornare il comportamento (ad esempio una mappa serializzabile). Si hanno per avere l'interfaccia e l'implementazione appropriata.

+2

Supponevo che volesse assegnare oggetti esistenti alla variabile, ad es. un oggetto HashMap. – skaffman

+2

Penso che voglia avere una mappa serializzabile come firma variabile, ma essere ancora in grado di usare HashMap, TreeMap, ecc. I.e., MyMap map = new HashMap(); non sta andando a lavorare penso. – JeeBee

3

È possibile raggiungere questo obiettivo, rendendo la propria interfaccia, che si estende le interfacce che si desidera

public interface SerializableMap<K, V> extends Map<K, V>, Serializable { 

} 
11

si può fare con i generici, ma non è abbastanza:

class MyClass<T,K,V extends Serializable & Map<K,V>> { 

    T myVar; 

} 
+1

Probabilmente vuoi aggiungere una K & V a questo. –

+0

In genere, anche tu hai bisogno di molta bruttezza nel modo in cui lo usi. –

+0

Sì, succherebbe quello grosso, e preferirei strapparmi le unghie piuttosto che usare quello che ho scritto sopra, ma l'altro sta pagando i soldi qui. – skaffman

0

Non si può realmente farlo se si desidera continuare a utilizzare le implementazioni esistenti Map.

Un'alternativa sarebbe quella di fare una classe di supporto, e aggiungere un metodo come questo:

public static Serializable serializableFromMap(Map<?, ?> map) { 
    if (map instanceof Serializable) { 
     return (Serializable)map; 
    } 
    throw new IllegalArgumentException("map wasn't serializable"); 
} 
2

ho votato fino risposta di Brian, ma ha voluto aggiungere un po 'di più alto livello pensato ..

Se si guarda attraverso l'SDK, si scoprirà che raramente (o mai) passano attorno a oggetti di raccolta reali.

Il motivo è che non è una buona idea. Le collezioni sono estremamente protette.

La maggior parte delle volte si desidera eseguire una copia prima di passarla e passare la copia in modo che qualsiasi modifica alla raccolta non cambi l'ambiente per qualcos'altro che si basa su di essa.Inoltre, il threading diventa un incubo - anche con una collezione sincronizzata!

Ho visto due soluzioni, una è estrarre sempre un array e passarlo. Questo è come l'SDK fa.

L'altro è quello di avvolgere SEMPRE le raccolte in una classe padre (e intendo dire incapsulare, non estendere). Ho preso questa abitudine e ne vale davvero la pena. In realtà non costa nulla perché non si duplicano comunque tutti i metodi di raccolta (in realtà si duplicano raramente nessuno di essi). In effetti, ciò che si finisce per fare è spostare la funzionalità "Utility" da altre classi distribuite su tutto il codice nella classe wrapper, che è dove avrebbe dovuto essere in primo luogo.

Qualsiasi metodo con una firma che corrisponda a "metodo (raccolta, ...)" dovrebbe quasi certamente essere un metodo membro di tale raccolta, così come qualsiasi loop che itera sulla raccolta.

Devo solo buttarlo fuori ogni tanto perché è una di quelle cose che non ho avuto per un po '(perché nessuno ha sostenuto il concetto). Sembra sempre che abbia qualche inconveniente, ma avendo fatto questo per un po 'e vedendo i problemi che ha risolto e cancellato il codice, non riesco nemmeno a immaginare alcun possibile inconveniente, è tutto ok.

+0

Sono d'accordo con questo. Non mi è chiaro il motivo per cui accettare 'Map's arbitrarie è desiderabile, piuttosto che un'interfaccia semanticamente significativa specifica per il codice in questione. –

6

E 'possibile farlo utilizzando alcuni trucchi generici:

public <T extends Map<?,?> & Serializable> void setMap(T map) 

Il codice precedente utilizza farmaci generici per costringere a passare una mappa che implementa entrambe le interfacce. Tuttavia, si noti che una conseguenza di ciò è che quando si passano effettivamente le mappe, sarà probabilmente necessario contrassegnarle come serializzabili o di un tipo di mappa che è già serializzabile. È anche un po 'più difficile da leggere. Vorrei documentare che la mappa deve essere serializzabile e eseguire il test per questo.

0

No, hai quasi bisogno di trasmettere.

Problemi correlati