2013-03-27 15 views
17

Sto implementando un comportamento che potrebbe trarre vantaggio dall'uso di riferimenti deboli in alcuni casi. Vorrei che l'utente della classe fosse in grado di indicare al momento della costruzione se questo è il caso o meno. Dal momento che si estende WeakReferenceReference a prima vista sembrerebbe avrei potuto fare qualcosa di simile (questo è un mockup, non quello che sto effettivamente cercando di fare):Perché non esiste un oggetto StrongReference?

public class Container<T> { 
    private boolean useWeakRef; 
    private Reference<T> ref; 

    public Container(boolean isWeak) { 
     useWeakRef = isWeak; 
    } 

    public void store(T val) { 
     if(useWeakRef) { 
      ref = new WeakReference<>(val); 
     } else { 
      ref = new StrongReference<>(val); 
     } 
    } 

    // May return null 
    public T get() { 
     return ref.get(); 
    } 
} 

Tuttavia non v'è alcuna StrongReference di classe, e secondo la Reference javadocs:

Poiché gli oggetti di riferimento sono attuate in stretta cooperazione con il garbage collector, questa classe non può essere derivata direttamente.

Quindi non posso creare la mia sottoclasse di riferimento che contiene un riferimento forte (ovvero normale) all'oggetto. Ciò sembra significare che non è possibile creare una classe che nasconde se utilizza i riferimenti Weak (o Soft) dal chiamante.

Non capisco veramente perché questa classe non esiste, un oggetto StrongReference deve semplicemente restituire sempre l'oggetto da get() a meno che clear() non sia stato chiamato. Perché manca questo? È un StrongReference incoerente con Reference in qualche modo? Sarebbe molto più semplice costruire oggetti di riferimento generici.

+0

è anche banale implementare un'interfaccia per tale funzionalità se davvero ne hai bisogno. –

+1

Sì, mi rendo conto che ci sono soluzioni alternative, ma presumo che i progettisti Java abbiano evitato intenzionalmente di includere questa classe apparentemente logica, e mi chiedo perché l'abbiano fatto. – dimo414

+0

+1. Esiste anche AtomicReference, che è un riferimento sicuro e sicuro per i thread, ma non implementa la stessa interfaccia. – Thilo

risposta

1

Guava's LocalCache utilizza una classe StrongValueReference che replica ciò che vorrei fare una classe StrongReference. Anche se è un guaio, Guava non espone questo come una classe pubblica, prendo questo come conferma che questa è una caratteristica mancante del JDK, e che è OK replicarla quando necessario.

Detto questo, la maggior parte dei casi di utilizzo che necessitano di astrarre il tipo di riferimenti con cui stanno lavorando sarà probabilmente in grado di utilizzare il comportamento Guava's Cache direttamente, come lo ero io. Incoraggerei chiunque incontrasse questa domanda per esplorare i meccanismi di memorizzazione nella cache di Guava esistenti prima di reinventare da soli questo comportamento di riferimento astratto.

3

Non è possibile eseguire la sottoclasse di riferimento perché non dispone di costruttori pubblici/protetti. Ma c'è una soluzione:

class StrongReference<T> extends WeakReference<T> { 
    private final T referent; 

    StrongReference(T referent) { 
     super(null); 
     this.referent = referent; 
    } 

    @Override 
    public T get() { 
     return referent; 
    } 

    // implement other methods 
} 
+4

Mi sembra molto logico. L'ereditarietà descrive una relazione "è una", e avrai difficoltà a sostenere che un "StrongReference" è un "WeakReference' :) – creinig

+0

concordato. L'implementazione che stavo usando (prima di passare a Guava) era un wrapper 'StrongOrWeakReference ' che conteneva un 'WeakReference ' o un 'T' direttamente, a seconda di come era stato costruito l'oggetto, e implementava' get() 'e 'chiaro()'. – dimo414

+1

@creinig: Sono sicuro che un riferimento forte è un superset di un riferimento debole, in realtà. Non solo ti permette di trovare l'oggetto, come fa un riferimento debole, ma lo mantiene anche in vita/previene la garbage collection su di esso. –

4

Quando ho bisogno di fare questo, ho appena creato un'interfaccia di riferimento personalizzato e una sottoclasse di banale WeakReference. è fastidioso ma è buono come si può fare.

public interface MyReference<T> { 
    public T get(); 
} 

public class MyWeakReference<T> extends WeakReference<T> implements MyReference<T> { 
} 

public class MyStrongReference<T> implements MyReference<T> { 
    // obvious implementation here ... 
} 

UPDATE:

per chiarire, non ho idea perché questo non è stato incluso nel JDK, in primo luogo (i, anche piaciuto che fosse stata), tuttavia, mi sento questa è una soluzione ragionevole.

per coloro che cercano la giustificazione di questa idea, l'ho trovato necessario quando si implementano cache personalizzate in cui la forza del riferimento fa parte della configurazione per la cache.

+0

Questo non risponde alla domanda. La domanda sta chiedendo perché gli sviluppatori Java non l'hanno implementato. –

+2

@StephenC - true, fa parte della domanda. tuttavia, la parte che dice "Questo sembra significare che non è possibile fare una classe che nasconde se utilizza riferimenti deboli (o" soft "dal chiamante" sembra implicare anche il desiderio di una "soluzione" al problema. – jtahlborn

Problemi correlati