2009-04-13 4 views
4

KürzlichEnumSet für vor-1.5 fake enums?

enum Thing { 

    /* etc etc */ 

    static final Set<Thing> allThings = EnumSet.allOf(Thing.class); 

} 

Ich möchte etwas ähnliches in pre 1.5 Java eine Menge von diesen getan Ich habe, also ich möchte so etwas wie:

final class Thing { 

    private Thing(); // control instances within class 

    static final Thing instance0 = new Thing(); 
    static final Thing instance1 = new Thing(); 

    static final Set allThings = // ????? 
} 

Wie soll ich das tun?

+1

Lassen Sie den Konstruktor von Thing sich dem statischen Set allThings hinzufügen. –

Antwort

4

Was ist das:

final class Thing { 

    static final Set allThings = new HashSet(); 

    private Thing() { 
     allThings.add(this); 
    } // control instances within class 

    static final Thing instance0 = new Thing(); 
    static final Thing instance1 = new Thing(); 
} 
3

Es gab keine direkte Entsprechung in Java vor 1.5.

Vor Java 1.5 gab es zwei (syntaktisch schrulligen) Optionen, wenn Sie sofort initialisiert werden wollte:

static final Set allThings = new HashSet(Arrays.asList(new Object[] { 
    instance0, instance1, // etc. 
})); 

oder

static final Set allThings = new HashSet() {{ 
    add(instance0); 
    add(instance1); 
    // etc. 
}}; 

Beide haben ihre Nachteile, though. Der einfachere Weg ist, einfach eine statische Methode zu machen

private static Set all() { 
    Set ret = new HashSet(); 
    ret.add(instance0); 
    ret.add(instance1); 
    // etc. 
} 

Sie haben noch keine neue Mitglieder in die Methode hinzufügen zu erinnern, aber es ist einfacher (für die meisten Menschen) zu lesen.

1

Es ist ein ziemlich gut definierte Muster auf, wie typsichere Aufzählungen in einer Pre-Jav 5-Umgebung zu definieren.

Es ist im Grunde eine Klasse mit public final static Felder für die Werte und einen privaten Konstruktor (oder mehr).

Die einzige "harte" Sache ist, Details wie Serialisierung richtig zu bekommen (im Grunde durch Implementierung readResolve()).

This Javaworld Tip geht ziemlich tief in der Sache und this one hat etwas mehr zu diesem Thema zu sagen.

0

In der folgenden Lösung erweitert jede Enum-Klasse eine abstrakte Basisklasse AbstractEnum, und ihre eigene Gruppe aller Werte wird automatisch generiert und in einer statischen Map in der Basisklasse gespeichert.

public abstract class AbstractEnum 
    { 
    private final static Map/*<Class,Collection<AbstractEnum>>*/ allEnums 
     = new HashMap(); 

    protected AbstractEnum() 
    { 
     Collection/*<AbstractEnum>*/ allValues 
     = (Collection) allEnums.get(getClass()); 
     if (allValues == null) 
     { 
     allValues = new HashSet(); 
     allEnums.put(getClass(), allValues); 
     } 
     allValues.add(this); 
    } 

    protected static Collection/*<AbstractEnum>*/ getAllValues(Class clazz) 
    { 
     return Collections 
     .unmodifiableCollection((Collection) allEnums.get(clazz)); 
    } 
    } 

    final class Thing extends AbstractEnum 
    { 
    final static Thing thing0 = new Thing(); 

    final static Thing thing1 = new Thing(); 

    private Thing() 
    {} 

    static Collection/*<Thing>*/ getAllValues() 
    { 
     return getAllValues(Thing.class); 
    } 
    } 

beachten, dass es immer noch einige weitere wichtige Merkmale, wie zB Thread-Sicherheit und die Serialisierung muss (wie in dem Beitrag von Saua beschrieben).