2009-05-14 6 views
0

Grundsätzlich hätte ich gerne ein Wörterbuch, das eine Abstinenz über Legacy #define Direktiven ist.Elegante Art, große statische typsichere Wörterbuch in Java zu halten - oder Code zu groß zu vermeiden

Ich habe eine alte Header-Datei, die 6000 + definiert enthält, die als Flag parametersome Funktion verwendet werden und diese definiert einen Typ der Entität parameter bezeichnen.

In C habe ich

GetParameter(... , T_CTITLE, ...); 

In Java würde Ich mag

Connector.getParameter(Parameter.CTITLE, ...); 

Und Parameter jeder Logik kapseln würde aufzurufen, die mit dem Erhalten der Parameter aus der Bibliothek zugeordnet ist.

Parameterinstanzen werden automatisch aus dem Header extrahiert und in Java-Code konvertiert, aber das Problem ist, dass die Parameter-Klasse zu groß wird - d. H. Ich bekomme code too large Kompilierungsfehler (lassen Sie mich unterstreichen: es gibt mehr als 6000 Parameter).

Und ich würde begeistert sein, diese Abstraktion in einer Weise zu machen, die IDE ermöglicht, Autovervollständigung zu verwenden, und die Idee des Speicherns von Parameterobjekten in zB HashMap sehr ablehnen würde.

EDIT: Parameter Klasse wird in folgenden Weise definiert:

public Parameter{ 
    /** logic **/ 
    public static final Parameter<T> parameter1 = new Parameter<T>("NAME", "T", 0xAAB); 
    ... 
    public static final Parameter<T> parameter6000 = new Parameter<T>("FOO", "T", 0xZZZ); 
} 

Antwort

4

Eine offensichtliche Hack zu jeder Partition in eine große Vererbungskette sein würde, oder besser Partition in Schnittstellen (keine Notwendigkeit für den public static final Lärm) und einem Schnittstelle, um sie alle zu erben.

Sie könnten Speicherplatz sparen, indem Sie den Erstellungscode verkleinern. Statt:

new Parameter<T>("NAME", "T", 0xAAB) 

Ein minimalistischer Ansatz wäre:

parameter("NAME T AAB") 

Einzelheiten zu Einschränkungen finden section 4.10 der JVM Spec (2nd Ed). Um zu sehen, wie Ihr kompilierter Code aussieht, verwenden Sie javap-c.

+0

serialisierte Formen sind gut ... –

+0

Ich werde versuchen Sie, es über paar Intercfaces aufzuteilen, wie Sie vorgeschlagen haben. –

+0

+1 für die LOTR-Referenz –

0

erweitern auf Tom Hawtins Beitrag, erwägen, JSON zu verwenden, um Struktur zu kodieren.

Oder noch besser, anstatt die Parameter in Ihrem Java-Code fest zu codieren, fügen Sie sie in eine XML- oder JSON-Datei (oder eine Eigenschaftendatei) ein, die in die JAR-Datei gesaugt wird.

+0

Ich möchte die automatische Vervollständigung der IDE aktivieren, die mit nichts funktioniert, das kein Java-Objektmitglied ist. –

+0

ahhhhhhhhh gotit. –

1

Vielleicht verstehe ich nicht, was Sie richtig machen wollen, aber das sieht wie eine perfekte Verwendung für ein Enum für mich aus. Da Sie Funktionen zu Enums hinzufügen können, sollten sie in der Lage sein zu tun, was Sie wollen, solange Ihre Version von Java neu genug ist (1.5+). Sie serialisieren auch!

Und ja, es funktioniert mit Autocomplete, obwohl eine Liste von 6000 groß ist.

Ich weiß nicht, ob es eine Grenze für die Größe eines Enum gibt, aber Sie könnten herausfinden.

Ex:

public enum Parameter { 
    NAME("Pending", "T", 0xAAB), FOO("Foo", "T", 0x1FC); 

    private final String displayValue; 
    private final char myChar; 
    private final int someNum; 

    private Parameter(String display, char c, int num) { 
     this.displayValue = display; 
     this.myChar = c; 
     this.someNum = num; 
    } 

    public String getDisplayValue() { 
     return displayValue; 
    } 

    public char getMyChar() { 
     return myChar; 
    } 

    public int getSomeNum() { 
     return someNum; 
    } 
} 

Jetzt können Sie hiermit die Art der Sache tun Sie wollen. Ex:

System.out.println("Hi, the value is " + Parameter.NAME.getSomeNum()); 

Da sie nicht während der Laufzeit ändern (immerhin #DEFINEs nicht kann), sollte eine ENUM die Rechnung passen.

Was die reine Größe betrifft, könnte es sein, dass Sie versuchen, sie leicht zu katogorisieren, und fügen Sie sie in ein paar Enum-Gruppen ein.

Dies gibt Ihnen die Möglichkeit, die Metadaten (die Zahlen) zuzuordnen, Auto-Vervollständigen, ==, und so weiter.

+0

Enum war mein erster Ansatz :) Auch generiert 'Code zu groß' kompilieren Fehler aufgrund der großen Menge an Werten. –

+0

Dang. Ich denke, es gibt ein Limit. Es würde die Rechnung ziemlich gut passen, wenn Sie Ihre #DEFINEs in Gruppen schneiden, aber ich merke, dass das ein großes Refactoring ist. Sie könnten tun, was Sie in Ihrem Code in der Q haben, aber alles beim Laden der Klasse in einem statischen Block generieren. Das ist meine beste Schätzung. Sie würden jedoch die automatische Vervollständigung verlieren. – MBCook

+0

Der statische Block hat auch Größenbeschränkungen. . . Ich habe einen statischen Block pro Parameter;) –

0

Ich denke, das ist was du willst. Ich denke, ‚T‘ der Typ ist, und Sie wollen Generika verwenden, so dass der Benutzer muss nicht die #define Werte Stimmen:

public class Parameter<T> { 

    public final static Parameter<String> NAME = new Parameter<String>("hello"); 
    // .. 5998 more declarations 
    public final static Parameter<Integer> FOO = new Parameter<Integer>(0xff0b); 


    private T value; 
    private Parameter(T value) { 
     this.value = value; 
    } 
    public T getValue() { 
     return value; 
    } 
} 

Zugriff auf einen Parameter rufen Sie einfach an:

String value = Parameter.NAME.getValue(); 

Die Java-Konstante ist gleich dem #defines-Namen, das generische gibt den Typ wieder und wir müssen den Wert nur an den Konstruktor übergeben. Code-Abschluss funktioniert gut :)

+0

Das ganze Problem ist, dass es zu viele dieser Parameter gibt. . . und ich bekomme Code zu groß, Kompilierfehler. –

1

Grundsätzlich denke ich, dass die Multi-Interface-Ansatz ist der Weg zu gehen. So würde ich diese Lösung strukturieren; Ich weiß nicht, was das zweite Argument Ihres Parameter-Konstruktors bedeutet, also habe ich es ignoriert.

In .../com/IhreFirma/legacydefines/Parameter.java:

package com.yourcompany.legacydefines; 

public class Parameter<T> { 
    private final String name; 
    private final T val; 

    private Parameter(String name, T val) { 
    this.val = val; 
    this.name = name; 
    } 

    public static <T> Parameter<T> newParameter(String name, T val) { 
    return new Parameter<T>(name, val); 
    } 

    // then, standard getters for "name" and "val" 
} 

In .../com/IhreFirma/legacydefines/Parameters1.java:

package com.yourcompany.legacydefines; 

import static com.yourcompany.legacydefines.Parameter.newParameter; 

interface Parameters1 { 
    public static Parameter<String> Parameter0001 = newParameter("ABC", "ABCVAL"); 
    // ... 
    public static Parameter<Integer> Parameter0999 = newParameter("FOO", 0xABCD); 
} 

In. ../com/yourcompany/legacydefines/Parameters2.java:

package com.yourcompany.legacydefines; 

import static com.yourcompany.legacydefines.Parameter.newParameter; 

interface Parameters2 { 
    public static Parameter<String> Parameter1001 = newParameter("DEF", "DEFVAL"); 
    // ... 
    public static Parameter<Integer> Parameter1999 = newParameter("BAR", 0x1002); 
} 

(und so weiter)

In .../com/IhreFirma/legacydefines/Parameters.java:

package com.yourcompany.legacydefines; 

interface Parameters extends Parameters1, Parameters2, Parameters3, Parameters4, 
          Parameters5, Parameters6, Parameters7 {} 

in Ihrem anderen Code Verwenden Sie dann nur Parameters.Parameter4562