Obtener variable por nombre de una Cadena

Código de ejemplo:

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

Ahora, supongamos que quiero que el usuario ingrese una cadena:

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

Entonces, digamos que el usuario ingresa potato . ¿Cómo recuperaría la variable llamada potato y haré cosas con ella? Algo como esto:

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

Busqué algunas cosas y no encontré mucho; Encontré una referencia a algo llamado “Reflection API”, pero parece demasiado complicado para esta simple tarea.

¿Hay alguna manera de hacer esto? De ser así, ¿qué es? Si “Reflection” realmente funciona y si es la única forma, ¿cómo lo usaría para hacer esto? La página de tutorial contiene todo tipo de material interno que no puedo entender.

EDITAR: Necesito mantener las String en las variables para lo que estoy haciendo. (No puedo usar un Map )

Usar el reflection no parece ser un buen diseño para lo que estás haciendo aquí. Sería mejor usar un Map por ejemplo:

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

O con Guava :

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

O con una enumeración :

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

En lugar de tratar de encontrar el valor de un nombre de variable, ¿por qué no utiliza un mapa con un par de clave / valor?

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

Entonces podrías acceder a las entradas de esta manera:

 vars.get(input); //would be 2 vars.get("stackOverflow"); //would be -4 

Los nombres de las variables solo están disponibles en el momento del comstackdor. La reflexión solo da acceso a declaraciones de clase y elementos declarados dentro de ellos, pero no a variables locales. Sospecho que un Map de algún tipo será una solución más adecuada para su problema real. Específicamente, echa un vistazo a HashMap y TreeMap .

Muy redundante , pero puede conservar sus nombres de variable cuando usa un mapa:

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

Pero una statement como esta:

 width = 42; 

no cambiaría el valor en el mapa:

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

Solo una nueva llamada de put correcciones que:

 width = 42; map.put("width", width); // or map.put("width", 42); 

Tengo una solución para este problema que no implica el uso de un mapa. Me topé con esta técnica porque teníamos varias variables que debían actualizarse en función de algo dentro del nombre de la variable en sí. Sin embargo, la mejor manera de hacerlo es usar los getters / setters en lugar de las variables.

Después de crear su clase, puede acceder a los métodos creando objetos de Método e invocándolos individualmente.

 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); However, this would not be limited to only incremental numbers, as long as you can get the string to match the method exactly. String value = "Potato";
Method mPotato = myClass.getClass().getMethod("get" + value+ "()"); mPotato.invoke(myClass);

Tengo otra solución sin un mapa:

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