2013-03-27 14 views
17

Wdrażam pewne zachowanie, które może korzystać z używania słabych odniesień przez pewien czas. Chciałbym, aby użytkownik klasy mógł w czasie budowy wskazać, czy tak jest, czy nie. Od WeakReference rozciąga Reference na pierwszy rzut oka wydaje się, mogę zrobić coś takiego (jest to makieta, a nie to, co ja rzeczywiście próbuje zrobić):Dlaczego nie ma obiektu 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(); 
    } 
} 

Jednak nie ma StrongReference klasy i zgodnie z Reference javadocs:

Ponieważ obiekty referencyjne są implementowane w ścisłej współpracy z modułem czyszczącym, ta klasa nie może być poddana subklasie bezpośrednio.

Nie mogę utworzyć własnej podklasy Referencji, która zawiera silne (tj. Normalne) odniesienie do obiektu. Wydaje się to oznaczać, że nie można utworzyć klasy, która ukrywa, czy używa odwołań Słaby (lub Miękki) od dzwoniącego.

Nie do końca rozumiem, dlaczego ta klasa nie istnieje, obiekt StrongReference powinien po prostu zawsze zwracać obiekt z get(), chyba że wywołano metodę clear(). Dlaczego tego brakuje? Czy StrongReference jest niespójne z Reference w jakiś sposób? To znacznie uprościłoby budowanie ogólnych obiektów odniesienia.

+0

To także trywialne, aby zaimplementować interfejs dla tej funkcji, jeśli naprawdę jej potrzebujesz. –

+1

Tak, zdaję sobie sprawę, że istnieją obejścia, ale zakładam, że projektanci Javy celowo uniknęli tej pozornie logicznej klasy i zastanawiam się, dlaczego to zrobili. – dimo414

+0

+1. Istnieje również AtomicReference, która jest silnym i bezpiecznym odnośnikiem, ale nie implementuje tego samego interfejsu. – Thilo

Odpowiedz

1

Guava LocalCache używa klasy StrongValueReference, która replikuje to, co chcę zrobić, aby wykonać klasę StrongReference. Chociaż szkoda, Guava nie ujawnia tego jako klasy publicznej, przyjmuję to jako potwierdzenie, że jest to brakująca funkcja JDK, i że można ją w razie potrzeby powtórzyć.

To powiedziawszy, większość przypadków użycia, które wymagają wyodrębnienia rodzaju referencji, z którymi pracują, prawdopodobnie będzie w stanie bezpośrednio używać, tak jak ja, zachowania Guava's Cache. Zachęcam każdego, kto natknie się na to pytanie, aby zbadał istniejące mechanizmy buforowania Guavy, zanim sami wymyślą te abstrakcyjne referencje.

3

Nie można odwoływać się do podklasy, ponieważ nie ma ona publicznych/chronionych konstruktorów. Ale istnieje obejście:

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

To wygląda na bardzo hackish do mnie. Dziedziczenie opisuje relację "jest", a będziesz mieć problem ze stwierdzeniem, że "StrongReference" to "' WeakReference' :) – creinig

+0

Zgoda. Implementacja, której używałem (zanim przełączyłem się na Guava) była opakowaniem 'StrongOrWeakReference ', które miało albo 'WeakReference ' albo 'T' bezpośrednio, zależnie od tego, jak obiekt został skonstruowany, i zaimplementowało' get() 'i 'clear()'. – dimo414

+1

@creinig: Jestem prawie pewien, że silne odniesienie jest w rzeczywistości nadzbiorem słabego odniesienia. Nie tylko pozwala ci znaleźć obiekt, jak czyni to słabe odniesienie, ale także utrzymuje go przy życiu/zapobiega zbieraniu śmieci na nim. –

4

kiedy już potrzebne, aby to zrobić, po prostu stworzony niestandardowy interfejs odniesienia i trywialne podklasę WeakReference. to denerwujące, ale jest tak dobre, jak tylko możesz.

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:

do wyjaśnienia, nie mam pojęcia dlaczegoten nie został uwzględniony w JDK w pierwszym miejscu (ja też, żeby to było), ale czuję jest to rozsądne obejście.

dla tych, którzy szukają usprawiedliwienia dla tego pomysłu, stwierdziłem, że jest to konieczne przy wdrażaniu niestandardowych pamięci podręcznych, w których siła odniesienia jest częścią konfiguracji pamięci podręcznej.

+0

To nie odpowiada na pytanie. Pytanie brzmi: DLACZEGO programiści Javy tego nie zaimplementowali. –

+2

@StephenC - prawda, to część pytania. jednak część, która mówi: "Wydaje się to oznaczać, że niemożliwe jest stworzenie klasy, która ukrywa, czy używa referencji Słaby (lub Miękki) od osoby dzwoniącej" zdaje się sugerować również "rozwiązanie" problemu. – jtahlborn

Powiązane problemy