Generisk Fabrikker og MAP-verdier

stemmer
1

Jeg har en klasse med Maps fra Ks til Set<V>s, i flere forskjellige Vs. Jeg ønsker å bruke en generisk fabrikk ala:

protected static <T> Set<T> SetFactory(int size) {
        return new HashSet<T>(size);
}

å gjøre noe sånt

for (K key : keySet) map.put(key, SetFactory());

og har den generiske delen arbeid (jeg får en kompileringsfeil, type mismatch mellom Set<Object>og Set<V>), som det gjør medSet<V> x = SetFactory();

Finnes det alternativer til å sende en Class<V>argument til SetFactory()?

Publisert på 21/09/2009 klokken 18:31
kilden bruker
På andre språk...                            


5 svar

stemmer
0

Du trenger en eksplisitt oppdrag:

for (K key : keySet) {
  Set<V> mySet = setFactory(20);
  map.put(key, mySet);
}

Uten det, er det ikke mulig for kompilatoren å vite hvilken type <V>

Svarte 21/09/2009 kl. 18:40
kilden bruker

stemmer
0

Apache Commons samlinger gir en LazyMap der du leverer en fabrikk objekt som skaper verdiene av kartet. Du kan levere en fabrikk som skaper dine Angi verdier.

Nå gjør Commons samlinger ikke bruke generics, men det er en generisk port av det her .

Jeg håper jeg tolket spørsmålet ditt riktig - det var ganske forvirrende.

Svarte 21/09/2009 kl. 18:43
kilden bruker

stemmer
0

Hvis du absolutt må ha det på en linje du kan sette en baloney oppdrag i put:

 Set<V> s = null;
 for (K key : keySet) map.put(key, s = setFactory());

Men det svaret er mer å vise en annen måte å gjøre det, faktisk ikke foreslå det er en bedre måte.

Svarte 21/09/2009 kl. 18:48
kilden bruker

stemmer
0

HRM, faktisk dette ser ut til å fungere:

protected static <K,V> Map<K,Set<V>> mapFactory(Collection<K> keys) {
    Set<V> holder;
    Map<K,Set<V>> result = new HashMap<K,Set<V>>(keys.size());
    for (K key : keys) result.put(key, holder = SetFactory());
    return result;
}

og selv får meg ut av irritasjonen av å måtte utgangspunktet fordele kart også. Jeg antar at jeg må legge til en fabrikk for å argumentlisten, hvis jeg ønsker å faktisk være i stand til å overstyre klassen.

Svarte 21/09/2009 kl. 18:48
kilden bruker

stemmer
2

Jeg forstår ikke helt problemet. Er dette hva du leter etter?

class MyClass {

  protected static <T> Set<T> SetFactory(int size)
  {
    return new HashSet<T>(size);
  }

  protected static <K, V> Map<K, Set<V>> mapFactory(Collection<K> keys)
  {
    Map<K, Set<V>> result = new HashMap<K, Set<V>>(keys.size());
    for (K key : keys)
      result.put(key, MyClass.<V>SetFactory(20));
    return result;
  }

}

Merk eksplisitt typeparameteren ( <V>) på den generiske metode påkalling.


Oppdater:

Jeg er sannsynligvis feil, men sier det ikke er støpt virker som semantikk for meg - å måtte sette MyClass. på forsiden virker ganske nær til å måtte kaste. Kan du forklare forskjellen?

En støpt ville være (Set<V>) SetFactory(20), og det ville generere en kompilator advarsel om typen sikkerhet, fordi med type sletting er det ingen måte å kontrollere at kjøretidstype resultatet av SetFactoryfunksjonen har en type V.

Ved hjelp av en type parameter på metodekallet er mye som å si new HashSet<V>(). Når du starter en konstruktør av en generisk klasse, må du spesifisere hvilken type argumenter for konstruktøren. Når du starter en generisk metode, må typeparametere angis. Ofte disse kan utledes fra et oppdrag av resultatet av metoden, eller fra metodens parametre, men ikke alltid.

Men det er ikke en støpt. En støpt alltid utfører en type sjekk ved kjøring. Spesifisere generisk type som jeg viser her fungerer ved kompilering-tiden.

Svarte 21/09/2009 kl. 19:24
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more