2015-05-21 8 views
12

Sto cercando di capire perché java.util.Properties è stato implementato in questo modo. Ha due interfacce: getProperty/setProperty che accetta solo stringhe e put/get che accetta qualsiasi oggetto come valore. Queste due interfacce sembrano essere sovrapposte, quindi una stringa aggiunta con put() può essere recuperata usando getProperty().Inserimento di oggetti in java.util.Properties

Sembra che ci siano alcuni problemi con questa strana interfaccia ibrida. L'inserimento di un oggetto che sovrascrive una proprietà stringa ha l'effetto collaterale di cancellare il valore stringa, producendo null come risultato getProperty. Aggiungere un intero o qualche altro valore con una semplice traduzione di stringhe potrebbe essere frainteso come valore di una proprietà reale (ma come proprietà è sempre nullo).

La mia domanda è: c'è una vera ragione pratica per questo? O è un'implementazione semicotta come sospetto?

+0

Impossibile eseguire il backup, ma sospetto fortemente che il problema sia la compatibilità con le versioni precedenti. 'Proprietà' estende' Hashtable', che è una vecchia classe di prima dei generici; questo significa che se tu avessi un 'Proprietà', avresti potuto chiamare' properties.put (qualunque cosa, qualunque cosa) '. Quando arrivarono i generici, i Java volevano mantenere il codice compatibile all'indietro, il che significava aver esteso "Hashtable ". – yshavit

+0

'Properties' è una sottoclasse di' Hashtable', senza override di 'get' /' put', quindi il comportamento. 'getProperty' /' setProperty' sono versioni digitate di 'get' /' put'. È una questione di storia e non di nascondersi. –

risposta

10

Joshua Bloch menzioni esplicitamente in Effective Java

[dal Capitolo 4] Nel caso di Properties, i progettisti intesi che solo stringhe ammesse come chiavi e valori, ma l'accesso diretto al sottostante Hashtable permette questa invariante da violare. Una volta violato questo invariante, non è più possibile utilizzare altre parti dell'API Proprietà (load e store). Nel momento in cui questo problema è stato scoperto, era troppo tardi per correggerlo perché i client dipendevano dall'uso di chiavi e valori nonstring.

Quel testo è nel contesto dell'uso della composizione sull'ereditarietà. In pratica sta usando questo come un esempio di quando la composizione dovrebbe essere usata al posto dell'ereditarietà. Se Properties ha avvolto un Map invece di estenderne uno, avrebbe potuto applicare l'invarianza dell'uso di String come chiavi e valori.

Quindi la risposta è: era una svista.

+1

Scegliere questa risposta perché spiega perché è stata implementata in questo modo, più che "non usare gli altri metodi". Come nota a margine, l'API java mail utilizza questo design per la configurazione di un factory socket SSL personalizzato. Oh java, il rapporto amore-odio che abbiamo. –

2

documentazione ufficiale dice

perché le proprietà eredita da Hashtable, la put e metodi putAll può essere applicato ad un oggetto di proprietà. Il loro uso è fortemente scoraggiato in quanto consentono al chiamante di inserire voci le cui chiavi o valori non sono stringhe. Al suo posto dovrebbe essere usato il metodo setProperty. Se il metodo store o save viene richiamato su un oggetto Properties "compromesso" che contiene una chiave o un valore non String, la chiamata avrà esito negativo. Allo stesso modo, la chiamata al metodo propertyNames o list avrà esito negativo se viene richiamata su un oggetto Properties "compromesso" che contiene una chiave non String.

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

5

accesso al put e get è il risultato di Properties che è un'estensione della Hashtable, e le due metodo non deve essere usato (ma non può essere nascosta da implementazione a causa della loro accesso del pubblico nella superclasse).

Il Javadocs hanno una bella nota su cui non si dovrebbe utilizzare gli stessi metodi, e dovrebbero invece solo le stringhe di utilizzo:

Perché Properties eredita da Hashtable, i put e putAll metodi possono essere applicati ad un Properties oggetto. Il loro uso è fortemente scoraggiato in quanto consentono al chiamante di inserire voci le cui chiavi o valori non sono Strings. Al suo posto dovrebbe essere usato il metodo setProperty. Se il metodo store o save viene chiamato su un oggetto "compromesso" Properties che contiene una chiave o un valore non- String, la chiamata avrà esito negativo. Analogamente, la chiamata al metodo propertyNames o avrà esito negativo se viene richiamata su un oggetto "compromesso" Properties che contiene una chiave diversa da String.

Come @yshavit nota, sarebbe più sensato per Properties di estendere Hashtable<String, String> di una tabella hash di due oggetti, ma questo era probabilmente una decisione presa per mantenere la compatibilità all'indietro, come tutti i programmi utilizzando get/put con qualsiasi gli oggetti non stringa sarebbero stati interrotti da un tale cambiamento.

+0

Ma questo non risolve una parte cruciale della domanda, motivo per cui i metodi get/put funzionano su 'Object' invece di' String'.Cioè, perché non estende 'Hashtable '? (Per il mio commento sopra, sospetto fortemente che sia compatibile con le versioni precedenti - ma non ho prove specifiche.) – yshavit

+0

@yshavit Buona nota; Sono d'accordo che è quasi sicuramente per la retrocompatibilità, e ho aggiunto una nota del genere nella risposta. – Vulcan

0

Dal Java Docs

Poiché Proprietà eredita dalla Hashtable, put e metodi putAll può essere applicato ad un oggetto Properties.Il loro uso è fortemente scoraggiato in quanto consentono al chiamante di inserire voci le cui chiavi o valori non sono stringhe. Al suo posto dovrebbe essere usato il metodo setProperty. Se il metodo di salvataggio o di salvataggio viene richiamato su un oggetto "compromesso" che contiene una chiave o un valore non stringa, la chiamata avrà esito negativo. Analogamente, la chiamata al metodo propertyNames o list avrà esito negativo se viene richiamato su un oggetto Properties "compromesso" che contiene una chiave non String .

0

Properties estende Hashtable, in modo da poter usare Properties ovunque è possibile utilizzare un Hashtable.

La classe Hashtable è da dove provengono le funzioni get() e put().

0

put(key, value) e get(key) sono i resti di una decisione discutibile per avere Properties estendere Hashtable indietro nel giorno. Questo comportamento non può essere modificato poiché interromperà la compatibilità con le versioni precedenti, ma qualsiasi guida di stile decente, inclusa la documentazione API stessa, consiglierà di non utilizzare mai questi metodi.

0

Come altri hanno già detto, dovresti usarlo solo per le stringhe. Ci sono modi di serializzare un oggetto come una stringa e recuperarlo, ma ovviamente non è pensato per quello. Capisco che sia davvero fastidioso dal momento che è il più vicino possibile ad un modo multipiattaforma di salvare e recuperare i dati delle app. Per quanto ne so, non esiste un modo ufficiale per salvare cose diverse dalle stringhe in una cartella nascosta all'utente, nonostante il fatto che la maggior parte dei sistemi operativi disponga di directory di appdata.

Problemi correlati