21

示例代码:

int width = 5;
int area = 8;
int potato = 2;
int stackOverflow = -4;

现在,假设我想让用户输入一个字符串:

String input = new Scanner(System.in).nextLine();

然后,说用户输入potato。我将如何检索命名的变量potato并对其进行处理?像这样的东西:

System.getVariable(input); //which will be 2
System.getVariable("stackOverflow"); //should be -4

我查了一些东西,并没有找到太多;我确实找到了对“反射 API”的引用,但这对于这个简单的任务来说似乎太复杂了。

有没有办法做到这一点,如果是这样,它是什么?如果“反射”确实有效并且它是唯一的方法,那么我将如何使用它来做到这一点?它的教程页面包含各种我无法理解的内部内容。

编辑:我需要将Strings 保留在我正在做的事情的变量中。(我不能使用Map

4

6 回答 6

17

对于您在这里所做的事情,使用反射似乎不是一个好的设计。最好使用Map<String, Integer>例如:

static final Map<String, Integer> VALUES_BY_NAME;
static {
    final Map<String, Integer> valuesByName = new HashMap<>();
    valuesByName.put("width", 5);
    valuesByName.put("potato", 2);
    VALUES_BY_NAME = Collections.unmodifiableMap(valuesByName);
}

或与番石榴

static final ImmutableMap<String, Integer> VALUES_BY_NAME = ImmutableMap.of(
    "width", 5,
    "potato", 2
);

或使用枚举

enum NameValuePair {

    WIDTH("width", 5),
    POTATO("potato", 2);

    private final String name;
    private final int value;

    private NameValuePair(final String name, final int value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return name;
    }

    public String getValue() {
        return value;
    }

    static NameValuePair getByName(final String name) {
        for (final NameValuePair nvp : values()) {
            if (nvp.getName().equals(name)) {
                return nvp;
            }
        }
        throw new IllegalArgumentException("Invalid name: " + name);
    }
}
于 2012-11-08T22:21:09.127 回答
4

变量名仅在编译器时可用。反射只允许访问类声明和在其中声明的项,但不能访问局部变量。我怀疑Map某种方式将是解决您实际问题的更合适的方法。具体来说,请查看HashMapTreeMap

于 2012-11-08T22:21:49.453 回答
3

与其尝试查找变量名的值,不如使用带有键/值对的 Map 呢?

Map<String, Integer> vars = new HashMap<String, Integer>();
vars.put("width",5);
vars.put("area",8);
vars.put("potato", 2);
vars.put("stackOverflow",-4);

然后你可以像这样访问输入:

vars.get(input); //would be 2
vars.get("stackOverflow"); //would be -4
于 2012-11-08T22:25:14.497 回答
2

对于这个问题,我有一个不涉及使用地图的解决方案。我遇到了这种技术,因为我们有几个变量需要根据变量名本身的内容进行更新。但是,最好的方法是使用 getter/setter 而不是变量。

创建类后,您可以通过创建 Method 对象并单独调用它们来访问方法。

public class FooClass

private String foo1;
private String foo2;

public String getFoo1();
public String getFoo2();

FooClass fooClass = new FooClass();

Method mFoo1 = fooClass.getClass().getMethod("getFoo" + increment + "()");

mFoo1 .invoke(fooClass);

但是,这不仅限于增量数字,只要您可以获得与方法完全匹配的字符串即可。

String value = "Potato";
Method mPotato = myClass.getClass().getMethod("get" + value+ "()");

mPotato.invoke(myClass);
于 2016-11-28T15:48:09.260 回答
1

我有另一个没有地图的解决方案:

class Vars {
    Integer potato, stack;
    public Vars(a,b) {
        potato=a;
        stack=b;
    }
}
Object object=(Object)new Vars(1,2);
Class<?> c = object.getClass();
Integer result=(Integer)c.getField("potato").get(object);
于 2017-06-05T15:02:09.633 回答
0

非常多余,但是您可以在使用地图时保留变量名:

int width = 5;
int area = 8;
int potato = 2;
int stackOverflow = -4;
Map<String, Integer> map = new HashMap<>();
map.put("width", width);
map.put("area", area);
map.put("potato", potato);
map.put("stackOverflow", stackOverflow);

但是这样的声明:

width = 42;

不会更改地图中的值:

String input = "width";
map.get(input); // <-- still returns 5.

只有一个新的 put 修复调用:

width = 42;
map.put("width", width);
// or
map.put("width", 42);
于 2012-11-08T22:50:32.100 回答