我在项目中使用BetterBeanBindings,如果我可以对其键不是String的Map进行绑定,那就太好了。
让我们举一个例子来解释这种情况:
public class Bean {
// ...
private Map<String, AnotherObject> mapOne;
private Map<SomeObject, AnotherObject> mapTwo;
// ...
public Map<String, AnotherObject> getMapOne() {
return this.mapOne;
}
public void setMapOne(Map<String, AnotherObject> mapOne) {
Map<String, AnotherObject> oldMapOne = this.mapOne;
this.mapOne = mapOne;
this.propertyChangeSupport.firePropertyChange("mapOne", oldMapOne, mapOne);
}
public Map<SomeObject, AnotherObject> getMapTwo() {
return this.mapTwo;
}
public void setMapTwo(Map<SomeObject, AnotherObject> mapTwo) {
Map<SomeObject, AnotherObject> oldMapTwo = this.mapTwo;
this.mapTwo = mapTwo;
this.propertyChangeSupport.firePropertyChange("mapTwo", oldMapTwo, mapTwo);
}
// ...
}
BBB能够对其键为String的地图进行绑定(也可能超过数字,如果我记得正确的甚至不是原始类型,它有标准的解析)允许这样做:
Bean bean;
// ...
Bindings.createAutoBinding(UpdateStrategy.READ_WRITE
bean, BeanProperty.create("mapOne.xxx"),
whateverBean, whateverProperty);
这会将bean.getMapOne().get("xxx")
的结果正确地绑定到第5和第4个参数中给定对象的给定属性,反之亦然。
但是,如果我们尝试使用mapTwo
Bindings.createAutoBinding(UpdateStrategy.READ_WRITE
bean, BeanProperty.create("mapTwo.xxx"),
whateverOtherOrNotBean, whateverOtherOrNotProperty);
绑定尝试解析bean.getMapTwo().get("xxx")
,因为这是属性定义中提供的内容,mapTwo
可能不是String
,返回null
。这是有道理的,因为绑定不必知道如何将String
从属性转换为解析所需的对象
有没有选择这样做?使用转换器可能有某种解决方法吗?
答案 0 :(得分:0)
我做了一个小的解决方法,对每个案例都不起作用,但是非常普遍。
事情是使用Map<K, V>
,它能够响应K
或String
类型的值,其中Map<String, V>
支持主地图。
StringBackedMap:
import java.util.Map;
import java.util.Set;
public interface StringBackedMap<K, V> extends Map<K, V> {
public V get(String key);
public boolean containsKey(String key);
public Set<Entry<String, V>> backerEntrySet();
public Set<String> backerKeySet();
}
StringBackedHashMap:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class StringBackedHashMap<K, V> extends HashMap<K, V> implements StringBackedMap<K, V> {
private static final long serialVersionUID = 1L;
private Map<String, V> backerMap;
public StringBackedHashMap() {
super();
init();
}
public StringBackedHashMap(int capacity) {
super(capacity);
init();
}
public StringBackedHashMap(int capacity, float loadFactor) {
super(capacity, loadFactor);
init();
}
public StringBackedHashMap(Map<? extends K, ? extends V> map) {
super(map);
init();
putAll(map);
}
private void init() {
this.backerMap = new HashMap<String, V>();
}
@Override
public V get(String key) {
return this.backerMap.get(key);
}
@Override
public V get(Object key) {
V value = super.get(key);
if (value == null) {
value = this.backerMap.get(key.toString());
}
return value;
}
@Override
public boolean containsKey(String key) {
return this.backerMap.containsKey(key);
}
@Override
public boolean containsKey(Object key) {
return super.containsKey(key) || this.backerMap.containsKey(key);
}
@Override
public Set<String> backerKeySet() {
return this.backerMap.keySet();
}
@Override
public Set<Entry<String, V>> backerEntrySet() {
return this.backerMap.entrySet();
}
@Override
public V put(K key, V value) {
V oldValue = super.put(key, value);
this.backerMap.put(key.toString(), value);
return oldValue;
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
if ((map != null) && (!map.isEmpty())) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
this.backerMap.put(entry.getKey().toString(), entry.getValue());
}
}
}
@Override
public V remove(Object key) {
V oldValue = super.remove(key);
this.backerMap.remove(key.toString());
return oldValue;
}
@Override
public void clear() {
super.clear();
this.backerMap.clear();
}
}