Ottieni variabile per nome da una stringa

Codice di esempio:

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

Ora, dì che voglio che l’utente inserisca una stringa:

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

Quindi, dire che l’utente inserisce la potato . Come posso recuperare la variabile denominata potato e fare cose con essa? Qualcosa come questo:

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

Ho cercato alcune cose e non ho trovato molto; Ho trovato un riferimento a qualcosa chiamato “API Reflection”, ma sembra troppo complicato per questo semplice compito.

C’è un modo per farlo, e se sì, cos’è? Se “Reflection” funziona davvero e se è l’unico modo, come utilizzarlo per farlo? La pagina del tutorial per questo ha tutti i tipi di cose interne che non riesco a capire.

EDIT: Ho bisogno di mantenere le String nelle variabili per quello che sto facendo. (Non posso usare una Map )

Usare la riflessione non sembra un buon design per quello che stai facendo qui. Sarebbe meglio usare una Map ad esempio:

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

Invece di cercare di trovare il valore di un nome di variabile, perché non usi una mappa con una coppia chiave / valore?

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

Quindi è ansible accedere agli input in questo modo:

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

I nomi delle variabili sono disponibili solo al momento del compilatore. Reflection fornisce solo l’accesso alle dichiarazioni di class e agli oggetti dichiarati al loro interno, ma non alle variabili locali. Sospetto che una Map di qualche tipo sia una soluzione più appropriata al tuo vero problema. In particolare, controlla HashMap e TreeMap .

Molto ridondante , ma è ansible mantenere i nomi delle variabili quando si utilizza una mappa:

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

Ma una dichiarazione come questa:

 width = 42; 

non cambierebbe il valore nella mappa:

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

Solo una nuova chiamata di mettere correzioni che:

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

Ho una soluzione per questo problema che non comporta l’utilizzo di una mappa. Mi sono imbattuto in questa tecnica perché avevamo diverse variabili che dovevano essere aggiornate in base a qualcosa all’interno del nome della variabile stessa. Tuttavia, il modo migliore per farlo è utilizzando i getter / setter piuttosto che le variabili.

Dopo aver creato la tua class, puoi accedere ai metodi creando oggetti Method e invocandoli 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);

Ho un’altra soluzione senza una mappa:

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