Holen Sie Variable nach Name aus einer Zeichenfolge

Beispielcode:

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

Nun möchte ich sagen, dass der Benutzer eine Zeichenfolge eingeben soll:

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

Dann sagen Sie, der Benutzer gibt potato . Wie würde ich die Variable namens potato abrufen und Sachen damit machen? Etwas wie das:

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

Ich sah ein paar Dinge auf und fand nicht viel; Ich habe einen Verweis auf etwas namens “Reflection API” gefunden, aber das scheint zu kompliziert für diese einfache Aufgabe.

Gibt es einen Weg dies zu tun, und wenn ja, was ist es? Wenn “Reflection” tatsächlich funktioniert und wenn es der einzige Weg ist, wie würde ich es dann dazu verwenden? Die Tutorial-Seite dafür hat alle möglichen internen Dinge, die ich nicht verstehen kann.

EDIT: Ich muss die String s in den Variablen für das, was ich mache, behalten. (Ich kann keine Map benutzen)

Die Verwendung von Reflektion erscheint nicht als gutes Design für das, was Sie hier tun. Es wäre besser, eine Map zu verwenden:

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

Oder mit Guava :

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

Oder mit einer enum :

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

Anstatt zu versuchen, den Wert eines Variablennamens zu finden, warum verwenden Sie nicht eine Map mit einem Schlüssel / Wert-Paar?

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

Dann könnten Sie wie folgt auf die Eingänge zugreifen:

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

Variablennamen sind nur zum Zeitpunkt des Compilers verfügbar. Reflection bietet nur Zugriff auf classndeklarationen und Elemente, die in ihnen deklariert sind, jedoch nicht auf lokale Variablen. Ich vermute, dass eine Map einer Art eine angemessenere Lösung für Ihr wirkliches Problem sein wird. Überprüfen Sie insbesondere HashMap und TreeMap .

Sehr redundant , aber Sie können Ihre Variablennamen behalten, wenn Sie eine Karte verwenden:

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

Aber eine Aussage wie diese:

 width = 42; 

würde den Wert in der Map nicht ändern:

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

Nur ein neuer Aufruf von put behebt:

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

Ich habe eine Lösung für dieses Problem, die keine Verwendung einer Karte beinhaltet. Ich stieß auf diese Technik, weil wir mehrere Variablen hatten, die auf der Grundlage von etwas innerhalb des Variablennamens selbst aktualisiert werden mussten. Der beste Weg dazu ist jedoch die Verwendung der Getter / Setter anstelle der Variablen.

Nachdem Sie Ihre class erstellt haben, können Sie auf die Methoden zugreifen, indem Sie Methodenobjekte erstellen und sie einzeln aufrufen.

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

Ich habe eine andere Lösung ohne Karte:

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