开发者

Alternative to String.equals for multiple compares (without enum)

开发者 https://www.devze.com 2023-02-20 16:12 出处:网络
I have thought about making enums for all my fields, but that doesn\'t look to cool either (i have many classes that implements similar methods). Is there a better way?

I have thought about making enums for all my fields, but that doesn't look to cool either (i have many classes that implements similar methods). Is there a better way?

public void writeAttribute(String attribute, Object value) {
    if (attribute.equals("title")) {
        title = (String) value;
    } else if (attribute.equals("description")) {
        description = (String) value开发者_JAVA技巧;
    } 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;
    }
}

Depending on the attribute parameter, i want to map the input value to the appropriate field. Is there a way to clean up/optimize my code? Writing .equals for every field isn't too elegant.


Rather than have an individual named member variable for each attribute, have you considered using a HashMap to store attributes? Your class would have an attribute map

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

and your method above reduces to

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

Since you're casting anyway, you would then have methods that cast the value appropriately when you access it, or cast it yourself at the point of access.


You could put your attribute/value pairs in a map:

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

And then mapping them to fields is a little cleaner:

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


you could do this: (feel free to use interface other than 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);
  }
}


I don't think if your method is OK to avoid such if-conditions, try do something like that:

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

where TITLE and DESCRIPTION is your final variables. If you won't have value in your Map for example in description then you'll have there null.


One way is using reflection, check out this post which explains how to get a field and then set the value for it.


You can try

public void writeAttribute(String attribute, Object value) {
    Field field = value.getClass().getDeclaredField(attribute);
    field.setAccesible(true);
    field.set(value);
}


We write preprocessed Java, for which you can find the processing code here.

It gives us string switches. However it adds an additional step to compilation. Files that require processing are named Foo.jpp and are processed to Foo.java, but the pervasiveness of String-based switches in our code more than makes up for this inconvenience.

Example:

/** 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
}


Since Java SE 7 (July 28, 2011) you can switch strings.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号