Festlegen Variablen mit Namen in Java
-
07-07-2019 - |
Frage
Ich bin auf der Suche nach dem Vorbild des etwas in Java zu implementieren:
class Foo{
private int lorem; //
private int ipsum;
public setAttribute(String attr, int val){
//sets attribute based on name
}
public static void main(String [] args){
Foo f = new Foo();
f.setAttribute("lorem",1);
f.setAttribute("ipsum",2);
}
public Foo(){}
}
... wo eine Variable wird basierend auf den Variablennamen ohne die Variablennamen hartcodiert und ohne irgendwelche andere Datenstrukturen zu verwenden. Ist das möglich?
Lösung
Hier ist, wie Sie setAttribute
implementieren könnte mithilfe von Reflektion (ich die Funktion umbenannt haben, es gibt unterschiedliche Reflexionsfunktionen für verschiedene Feldtypen):
public void setIntField(String fieldName, int value)
throws NoSuchFieldException, IllegalAccessException {
Field field = getClass().getDeclaredField(fieldName);
field.setInt(this, value);
}
Andere Tipps
In der Regel wollen Sie Reflexion verwenden. Hier ist eine gute Einführung in die Thema mit Beispielen
Insbesondere die „Werte im Wandel von Fields“ wird beschrieben, wie zu tun, was Sie tun möchten.
Ich nehme zur Kenntnis, dass der Autor sagt: „Diese Funktion ist extrem leistungsfähig und hat keine Entsprechung in anderen herkömmlichen Sprachen.“ Natürlich haben wir große Fortschritte in den letzten zehn Jahren (1998 wurde der Artikel geschrieben) in dynamischen Sprachen gemacht gesehen. Die oben ist ziemlich leicht gemacht in Perl, Python, PHP, Ruby, und so weiter. Ich vermute, dies ist die Richtung Sie basiert auf dem „eval“ Tag haben könnten.
Werfen Sie auch einen Blick auf BeanUtils , die von einigen der Komplexität der Verwendung von Reflexion verstecken Sie.
Die Frage ist spezifisch für ints, was hilfreich ist, aber hier ist etwas, etwas allgemeiner. Diese Art von Verfahren ist nützlich, wenn Sie in String
Darstellungen von Feldnamen / Feldwertepaaren geladen werden.
import java.lang.reflect.Field;
public class FieldTest {
static boolean isValid = false;
static int count = 5;
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
FieldTest test = new FieldTest();
test.setProperty("count", "24");
System.out.println(count);
test.setProperty("isValid", "true");
System.out.println(isValid);
}
public void setProperty(String fieldName, String value) throws NoSuchFieldException, IllegalAccessException {
Field field = this.getClass().getDeclaredField(fieldName);
if (field.getType() == Character.TYPE) {field.set(getClass(), value.charAt(0)); return;}
if (field.getType() == Short.TYPE) {field.set(getClass(), Short.parseShort(value)); return;}
if (field.getType() == Integer.TYPE) {field.set(getClass(), Integer.parseInt(value)); return;}
if (field.getType() == Long.TYPE) {field.set(getClass(), Long.parseLong(value)); return;}
if (field.getType() == Float.TYPE) {field.set(getClass(), Float.parseFloat(value)); return;}
if (field.getType() == Double.TYPE) {field.set(getClass(), Double.parseDouble(value)); return;}
if (field.getType() == Byte.TYPE) {field.set(getClass(), Byte.parseByte(value)); return;}
if (field.getType() == Boolean.TYPE) {field.set(getClass(), Boolean.parseBoolean(value)); return;}
field.set(getClass(), value);
}
}
Je nach Verwendungszweck können Sie Reflektion verwenden, wie oben empfohlen, oder vielleicht ein HashMap wäre besser geeignet ...
Sie möchten vielleicht einige der Reflexionsdaten zwischenzuspeichern, während Sie gerade dabei sind:
import java.lang.reflect.Field;
import java.util.HashMap;
class Foo {
private HashMap<String, Field> fields = new HashMap<String, Field>();
private void setAttribute(Field field, Object value) {
field.set(this, value);
}
public void setAttribute(String fieldName, Object value) {
if (!fields.containsKey(fieldName)) {
fields.put(fieldName, value);
}
setAttribute(fields.get(fieldName), value);
}
}