Ich versuche, Einweg-Datenbindung in Java für Swing-Objekte, nur als Übung. Derzeit füge ich für Swing-Objekte, die JTextComponent erweitern, einen Dokumentlistener hinzu, der auch den Sicherungsdatenspeicher aktualisiert.Field.set wirft IllegalArgumentException
public class Binder {
Map<JComponent, Map.Entry<WeakReference, Field>> map = new WeakHashMap<>();
AutoDocumentListener adl;
public Binder() {
adl = new AutoDocumentListener();
}
public void bind(Object instance, String varName, JComponent element, String property) {
Field field;
try {
field = instance.getClass().getDeclaredField(varName);
field.setAccessible(true);
map.put(element,
new AbstractMap.SimpleEntry<WeakReference, Field>(new WeakReference(instance), field));
if (element instanceof JTextComponent) {
element = (JTextComponent) element;
Document eldoc = ((JTextComponent) element).getDocument();
eldoc.putProperty("origin", element);
eldoc.addDocumentListener(adl);
} else { }
} catch (NoSuchFieldException | SecurityException ex) {
Logger.getLogger(Binder.class.getName()).log(Level.SEVERE, null, ex);
}
}
class AutoDocumentListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent evt) {
JTextComponent jc = (JTextComponent) evt.getDocument().getProperty("origin");
Map.Entry<WeakReference, Field> dataToUpdate = map.get(jc);
if (dataToUpdate != null) {
try {
Object data = jc.getText();
dataToUpdate.getValue().set(dataToUpdate.getKey(), data);
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(Binder.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void removeUpdate(DocumentEvent evt) {
}
@Override
public void changedUpdate(DocumentEvent e) {
}
}
}
Das Problem ist, in der folgenden Zeile bekomme ich ein Illegal:
dataToUpdate.getValue().set(dataToUpdate.getKey(), data);
java.lang.IllegalArgumentException: Can not set java.lang.String field org.jbind.test.TestClass.data to java.lang.ref.WeakReference
Soweit ich in der Dokumentation sehen, der Aufruf an Field.set korrekt ist. Also verstehe ich nicht, was falsch läuft.
Ich rufe die Funktion mit dem folgenden Code:
public class TestClass {
public String data = "Text1";
public void init() {
Binder binder = new Binder();
JTextField jtf = new JTextField(data);
binder.bind(this, "data", jtf, "");
jtf.setText("Text2");
System.out.println(data);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestClass().init();
}
});
}
}
Sie haben Recht. Ich weiß nicht, warum ich angenommen habe, dass die Zuweisung durch den SchwachenRef erfolgen kann. Habe es nicht gesehen, erbt ein get(). Vielen Dank. – DebD