Альтернатива String.equals для множественного сравнения (без enum) - PullRequest
2 голосов
/ 30 марта 2011

Я думал о создании перечислений для всех моих полей, но это тоже не выглядит круто (у меня есть много классов, которые реализуют подобные методы). Есть ли лучший способ?

public void writeAttribute(String attribute, Object value) {
    if (attribute.equals("title")) {
        title = (String) value;
    } else if (attribute.equals("description")) {
        description = (String) value;
    } else if (attribute.equals("room")) {
        room = (Room) value;
    } else if (attribute.equals("type")) {
        type = AppointmentType.valueOf((String) value);
    } else if (attribute.equals("guestCount")) {
        guestCount = (Integer) value;
    }
}

В зависимости от параметра attribute, я хочу отобразить вход value в соответствующее поле. Есть ли способ очистить / оптимизировать мой код? Запись .equals для каждого поля не слишком элегантна.

Ответы [ 8 ]

2 голосов
/ 30 марта 2011

Вместо того, чтобы иметь индивидуальную именованную переменную-член для каждого атрибута, вы рассматривали возможность использования HashMap для хранения атрибутов?Ваш класс будет иметь карту атрибутов

Map<String,Object> attributes = new HashMap<String,Object>();

, а ваш приведенный выше метод уменьшится до

public void writeAttribute(String attribute, Object value) {
    this.attributes.put(attribute,value);
}

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

0 голосов
/ 04 января 2012

Начиная с Java SE 7 (28 июля 2011 г.), вы можете переключать строки.

0 голосов
/ 22 июля 2011

Мы пишем предварительно обработанную Java, для которой вы можете найти код обработки здесь.

Это дает нам строковые ключи . Однако это добавляет дополнительный шаг к компиляции. Файлы, которые требуют обработки, называются Foo.jpp и обрабатываются до Foo.java, но распространенность переключателей на основе String в нашем коде более чем компенсирует это неудобство.

Пример:

/** set flags on added traps */
public void addTrap(JS key, JS function) throws JSExn {
    super.addTrap(key, function);
    // differentiate between read and write traps
    if (function.getFormalArgs().length != 1) {
        //#switch (JSU.toString(key))
        case "surface": set(SURFACE_READ_TRAP);
        case "visible": set(VISIBLE_READ_TRAP);
        case "Children": set(CHILDREN_READ_TRAP);
        //#end
        return;
    }
    //#switch (JSU.toString(key))
    case "x":         set(X_TRAP);
    case "y":         set(Y_TRAP);
    case "width":     set(WIDTH_TRAP);
    case "height":    set(HEIGHT_TRAP);
    case "minwidth":  set(MINWIDTH_TRAP);
    case "maxwidth":  set(MAXWIDTH_TRAP);
    case "minheight": set(MINHEIGHT_TRAP);
    case "maxheight": set(MAXHEIGHT_TRAP);
    case "contentwidth": set(CONTENTWIDTH_TRAP);
    case "contentheight": set(CONTENTHEIGHT_TRAP);
    case "surface":   set(SURFACE_TRAP); 
    case "visible":   set(VISIBLE_TRAP);
    case "Children":  set(CHILDREN_TRAP);
    case "Enter":     set(ENTER_TRAP);
    case "Leave":     set(LEAVE_TRAP);
    case "_Move":     set(_MOVE_TRAP);
    case "Move":      set(MOVE_TRAP);
    case "fontsize":  renderprops.setTrapFontsize(this);
    case "font":      renderprops.setTrapFont(this);
    case "shrink":    set(SHRINK_TRAP);
    case "hshrink":   set(HSHRINK_TRAP);
    case "vshrink":   set(VSHRINK_TRAP);
    //#end
}
0 голосов
/ 30 марта 2011

Вы можете попробовать

public void writeAttribute(String attribute, Object value) {
    Field field = value.getClass().getDeclaredField(attribute);
    field.setAccesible(true);
    field.set(value);
}
0 голосов
/ 30 марта 2011

Одним из способов является использование отражения, посмотрите эту запись , в которой объясняется, как получить поле, а затем задайте его значение.

0 голосов
/ 30 марта 2011

Я не думаю, что если ваш метод в порядке, чтобы избежать таких условий if, попробуйте сделать что-то вроде этого:

public void writeAttributes(Map<String, Object> attributesMap) {
    title = (String) attributesMap.get(TITLE);
    description = (String) attributesMap.get(DESCRIPTION);
    ...
}

где TITLE и DESCRIPTION - ваши окончательные переменные.Если у вас не будет значения на вашей карте, например, в описании, то у вас будет ноль.

0 голосов
/ 30 марта 2011

вы можете сделать это: (не стесняйтесь использовать интерфейс, отличный от Runnable)

interface AttributeEvaluator {
  Object getValue(String s);
}

enum Attribute {
  TITLE(new AttributeEvaluator() { public Object getValue(String str) { return (String)value; }),
  ROOM(new AttributeEvaluator() { public Object getValue(String str) { return (Room)value; });


  private Attribute(AttributeEvaluator r) {
    this.evaluator = evaluator;
  }

  public <T> T getValueOf(String str) {
    return (T)evaluator.getValue(str);
  }
}
0 голосов
/ 30 марта 2011

Вы можете разместить свои пары атрибут / значение на карте:

public void writeAttribute(String attribute, Object value) {
   attributeMap.put(attribute, value);
}

А затем сопоставить их с полями немного чище:

title = (String)map.get(value);
description = (String)map.get(value);
room = (Room)map.get(value);
type = AppointmentType.valueOf((String)map.get(value));
guestCount = (Integer)map.get(value);
...