Impostazione delle variabili per nome in Java
-
07-07-2019 - |
Domanda
Sto cercando di implementare qualcosa in Java sulla falsariga di:
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(){}
}
... dove una variabile è impostata in base al nome della variabile senza i nomi delle variabili hardcoded e senza utilizzare altre strutture di dati. È possibile?
Soluzione
Ecco come è possibile implementare setAttribute
usando reflection (ho rinominato la funzione; ci sono diverse funzioni di reflection per diversi tipi di campo):
public void setIntField(String fieldName, int value)
throws NoSuchFieldException, IllegalAccessException {
Field field = getClass().getDeclaredField(fieldName);
field.setInt(this, value);
}
Altri suggerimenti
In generale, si desidera utilizzare Reflection. Ecco una buona introduzione a argomento con esempi
In particolare, "Modifica dei valori dei campi" sezione descrive come fare quello che ti piacerebbe fare.
Noto che l'autore dice: "Questa funzione è estremamente potente e non ha equivalenti in altre lingue convenzionali." Certo, negli ultimi dieci anni (l'articolo è stato scritto nel 1998) abbiamo visto grandi passi avanti in linguaggi dinamici. Quanto sopra è fatto abbastanza facilmente in Perl, Python, PHP, Ruby e così via. Ho il sospetto che questa sia la direzione da cui potresti venire sulla base di "eval" tag.
Inoltre, dai un'occhiata a BeanUtils che può nascondere parte della complessità dell'uso della riflessione da te.
La domanda è specifica per gli ints, il che è utile, tuttavia qui c'è qualcosa di un po 'più generale. Questo tipo di metodo è utile se stai caricando in String
rappresentazioni di coppie nome campo / valore campo.
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);
}
}
A seconda dell'uso, puoi usare la riflessione come consigliato sopra, o forse una HashMap sarebbe più adatta ...
Potresti voler memorizzare nella cache alcuni dei dati di riflessione mentre ci sei:
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);
}
}