2010-07-09 6 views
8

POJO'm var ve bir (henüz oluşturulmamış) sınıfına sahip olanları listeler. POJO'nun bir Harita olarak erişilmesi için gerekli kodu otomatik olarak oluşturmak istiyorum. Bu iyi bir fikir mi, otomatik olarak yapmak mümkün mü ve bu şekilde tedavi etmek istediğim her POJO için bunu manuel olarak yapmam gerekiyor mu?Harita Oluştur <String, String> from POJO

sayesinde Andy

cevap

16

Bunun için Commons BeanUtilsBeanMap kullanabilirsiniz.

Map map = new BeanMap(someBean); 

Güncelleme:

public static Map<String, Object> mapProperties(Object bean) throws Exception { 
    Map<String, Object> properties = new HashMap<>(); 
    for (Method method : bean.getClass().getDeclaredMethods()) { 
     if (Modifier.isPublic(method.getModifiers()) 
      && method.getParameterTypes().length == 0 
      && method.getReturnType() != void.class 
      && method.getName().matches("^(get|is).+") 
     ) { 
      String name = method.getName().replaceAll("^(get|is)", ""); 
      name = Character.toLowerCase(name.charAt(0)) + (name.length() > 1 ? name.substring(1) : ""); 
      Object value = method.invoke(bean); 
      properties.put(name, value); 
     } 
    } 
    return properties; 
} 
: bu bir seçenek nedeniyle Android'de bazı belirgin kütüphane bağımlılık sorunlarına olmadığına göre, burada Reflection API küçük yardımı ile bunu nasıl temel bir başlama örneği

java.beans API'si mevcut olsaydı, o zaman şunları yapabilirsiniz:

public static Map<String, Object> mapProperties(Object bean) throws Exception { 
    Map<String, Object> properties = new HashMap<>(); 
    for (PropertyDescriptor property : Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors()) { 
     String name = property.getName(); 
     Object value = property.getReadMethod().invoke(bean); 
     properties.put(name, value); 
    } 
    return properties; 
} 
+0

Kutsal saçmalık! Bu çok kullanışlı görünüyor! Performans etkileri hakkında bir şey biliyor musunuz? –

+1

Yansıma her zaman bir performans maliyetine sahiptir. Yapacak bir şey yok. Fakat BeanUtils adamlarının olabildiğince optimize ettiğine güvenebilirsiniz. Oldukça popüler bir kütüphane. – BalusC

+0

Serin. POJO'larıma herhangi bir arabirim uygulamak zorunda mıyım yoksa get * adlandırma yeterli kullanıyor mu (Bir Builder kullanarak başlatılan değişmez POJO'lar/özel kurucular kullanıyorum)? –

1

Burada benim bağımlılığım olmadan kendi gerçekleştirmem var. Nesnenin durumunun bir kopyasını yapmak yerine, pojo üzerinde canlı bir Harita uygular. Android doesn't support java.beans, ancak bunun yerine openbeans'u kullanabilirsiniz.

import java.beans.*; // Or, import com.googlecode.openbeans.* 
import java.util.*; 

public class BeanMap extends AbstractMap<String, Object> { 
    private static final Object[] NO_ARGS = new Object[] {}; 
    private HashMap<String, PropertyDescriptor> properties; 
    private Object bean; 

    public BeanMap(Object bean) throws IntrospectionException { 
     this.bean = bean; 
     properties = new HashMap<String, PropertyDescriptor>(); 
     BeanInfo info = Introspector.getBeanInfo(bean.getClass()); 
     for(PropertyDescriptor property : info.getPropertyDescriptors()) { 
      properties.put(property.getName(), property); 
     } 
    } 

    @Override public Object get(Object key) { 
     PropertyDescriptor property = properties.get(key); 
     if(property == null) 
      return null; 
     try { 
      return property.getReadMethod().invoke(bean, NO_ARGS); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    @Override public Object put(String key, Object value) { 
     PropertyDescriptor property = properties.get(key); 
     try { 
      return property.getWriteMethod().invoke(bean, new Object[] {value}); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    @Override public Set<Map.Entry<String, Object>> entrySet() { 
     HashSet<Map.Entry<String, Object>> result = new HashSet<Map.Entry<String, Object>>(properties.size() * 2); 
     for(PropertyDescriptor property : properties.values()) { 
      String key = property.getName(); 
      Object value; 
      try { 
       value = property.getReadMethod().invoke(bean, NO_ARGS); 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
      result.add(new PropertyEntry(key, value)); 
     } 
     return Collections.unmodifiableSet(result); 
    } 

    @Override public int size() { return properties.size(); } 

    @Override public boolean containsKey(Object key) { 
     return properties.containsKey(key); 
    } 

    class PropertyEntry extends AbstractMap.SimpleEntry<String, Object> { 
     PropertyEntry(String key, Object value) { 
      super(key, value); 
     } 

     @Override public Object setValue(Object value) { 
      super.setValue(value); 
      return BeanMap.this.put(getKey(), value); 
     } 
    } 
}