Элегантный способ держать большой статический типобезопасный словарь в Java - или избегать слишком большого кода - PullRequest
0 голосов
/ 14 мая 2009

В основном я хотел бы иметь некоторый словарь, который является абстракцией по сравнению с устаревшими директивами #define.

У меня есть старый заголовочный файл, который содержит 6000+ определений, которые используются в качестве флаговых параметров некоторой функции, и эти определения обозначают один тип сущности parameter.

В C у меня есть

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

На Java я хотел бы позвонить

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

И параметр будет инкапсулировать всю логику, связанную с получением параметра из библиотеки.

Экземпляры параметров автоматически извлекаются из заголовка и преобразуются в код Java, но проблема в том, что класс параметров становится слишком большим - то есть я получаю code too large ошибку компиляции (позвольте мне подчеркнуть: существует более 6000 параметров).

И я был бы рад сделать эту абстракцию способом, позволяющим IDE использовать автозаполнение, и очень бы не понравилась идея хранения объектов Parameter, скажем, HashMap.

EDIT: класс параметров определяется следующим образом:

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);
}

Ответы [ 5 ]

4 голосов
/ 14 мая 2009

Очевидным хаком может быть либо разбиение на большую цепочку наследования, либо лучшее разбиение на интерфейсы (не нужно шума public static final) и один интерфейс для их всех.

Вы можете сэкономить место, уменьшив код создания. Вместо:

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

Минималистский подход:

parameter("NAME T AAB")

Подробнее об ограничениях см. раздел 4.10 спецификации JVM (2nd Ed). Чтобы увидеть, как выглядит ваш скомпилированный код, используйте javap -c.

1 голос
/ 15 мая 2009

В принципе, я думаю, что подход с несколькими интерфейсами - это путь. Вот как я бы структурировал это решение; Я не знаю, что имел в виду второй аргумент вашего конструктора параметров, поэтому я проигнорировал его.

В ... / com / yourcompany / 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 / yourcompany / 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);
}

(и т. Д.)

В ... / com / yourcompany / legacydefines / Parameters.java:

package com.yourcompany.legacydefines;

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

Затем в другом коде просто используйте Parameters.Parameter4562

1 голос
/ 14 мая 2009

Может быть, я не понимаю, что вы хотите сделать правильно, но это выглядит как идеальное использование для Enum для меня. Поскольку вы можете добавлять функции в Enums, они должны делать то, что вы хотите, если ваша версия Java достаточно свежа (1.5+). Они тоже сериализуются!

И да, он работает с автозаполнением, хотя список 6000 большой.

Я не знаю, существует ли ограничение на размер Enum, но вы могли бы узнать.

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;
    }
}

Теперь это позволяет вам делать то, что вы хотите. Пример:

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

Так как они не изменяются во время выполнения (в конце концов, #DEFINEs не может), ENUM должен отвечать всем требованиям.

Что касается чистого размера, возможно, вы попытаетесь немного их разделить и разделить на несколько групп Enum.

Это дает вам возможность связать метаданные (числа), выполнить автозаполнение, == и т. Д.

0 голосов
/ 14 мая 2009

Я думаю, это то, что вы хотите. Я предполагаю, что 'T' - это тип, и вы хотите использовать обобщения, чтобы пользователю не приходилось приводить значения #define:

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;
    }   
}

Для доступа к параметру просто позвоните:

String value = Parameter.NAME.getValue();

Константа java равна имени #defines, универсальный тип отражает тип, поэтому нам нужно только передать значение конструктору. Завершение кода работает отлично:)

0 голосов
/ 14 мая 2009

Расширяя пост Тома Хоутина, рассмотрите возможность использования JSON для кодирования структуры.

Или, что еще лучше, вместо того, чтобы жестко кодировать параметры в своем коде Java, поместите их в файл XML или JSON (или файл свойств), который будет добавлен в любой файл JAR, который вы в итоге создадите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...