JavaBean和Map的相互轉換
JavaBean和Map的相互轉換
一、JavaBean
1.什麼是JavaBean?
JavaBean其實就是一種遵循特定寫法的類,必須遵循一定的規範:
- 類必須由public修飾,並且保證有公共的無引數的構造器
- 包含操作屬性的的public方法,getter setter方法
- 欄位是私有的
一個JavaBean是由3部分組成,分別是屬性、方法、和事件。注意這裡的屬性是property,表示的是狀態,並不是欄位(Field)我們在剛開始學面向物件的時候其實有的時候也是用到了這個規範,我們寫的getter和setter方法,比如public void setName(String name){ this.name = name;}屬性其實就是name,在比如public int getAge(){return 19;},屬性其實就是age。一般的,我們寫getter個setter方法用的是IDE自己生成的,屬性和欄位同名。一定要區分屬性和欄位,它們並不是一個東西,也存在屬性名和欄位名不同。
2.內省機制
內省機制的作用就是用來檢視和操作JavaBean的屬性。
- 獲取JavaBean的屬性名
- 通過getter方法給屬性獲取值,通過setter給屬性設定值
常用的API
Introspector類中
static BeanInfo getBeanInfo(Class<?> beanClass) 在 Java Bean 上進行內省,瞭解其所有屬性、公開的方法和事件。 static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass) 在給定的“斷”點之下,在 Java Bean 上進行內省,瞭解其所有屬性和公開的方法。
可以看到在Introspector類中有兩個靜態方法可以獲得獲取JavaBean的資訊,一般的第一個會得到父類Object.class中的getClass方法,第二種會遮蔽掉Object類中的方法。返回一個BeanInfo,在BeanInfo介面中有一個方法可以獲得bean的描述器物件
MethodDescriptor[] getMethodDescriptors() 獲得 beans MethodDescriptor。
PropertyDescriptor[] getPropertyDescriptors() 獲得 beans PropertyDescriptor。
分別返回的是各自的描述器物件
Method getReadMethod() 獲得應該用於讀取屬性值的方法。 就是getter方法
Method getWriteMethod() 獲得應該用於寫入屬性值的方法。 就是setter方法
public class User {
private String name;
private int age;
private boolean man;
public String getName() {
return name;
}
...省略剩餘getter setter方法
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", man=" + man + "]";
}
public static void main(String[] args) throws Exception {
//獲得JavaBean的描述資訊
BeanInfo info = Introspector.getBeanInfo(User.class,Object.class);
//獲取JavaBean的屬性描述器物件,返回的是一個描述器陣列
PropertyDescriptor[] pds = info.getPropertyDescriptors();
//利用反射建立這個類的物件,當然這只是測試一下
User u = User.class.newInstance();
//對描述器物件進行迭代
for (PropertyDescriptor pd : pds) {
//獲取屬性名稱 和屬性的型別
System.out.println(pd.getName()+","+pd.getPropertyType()());
//獲取getset方法
Method get = pd.getReadMethod();
Method set = pd.getWriteMethod();
System.out.println("getter方法:"+get);
System.out.println("setter方法:"+set);
//用反射給name屬性設定值
if("name".equals(pd.getName())){
Method setter = pd.getWriteMethod();
setter.invoke(u, "xx");
Method getter = pd.getReadMethod();
Object o = getter.invoke(u);//獲取名字
System.out.println(o);
}
}
System.out.println(u);
}
}
二、JavaBean和Map的相互轉化
我們可以發現javabean和map之間有很多相似之處.在map中是一對鍵值對key-value,而在JavaBean中是屬性名-屬性值。現在對這兩種進行相互轉換
1.JavaBean轉化為Map
思路:把bean轉化為map,不過就是把bean中的屬性名給map的key,把屬性值給map中的value。在程式上表達,提供一個方法,傳入的是一個JavaBean物件,返回的是一個Map。
上程式碼:
//把JavaBean轉化為map
public static Map<String,Object> bean2map(Object bean) throws Exception{
Map<String,Object> map = new HashMap<>();
//獲取JavaBean的描述器
BeanInfo b = Introspector.getBeanInfo(bean.getClass(),Object.class);
//獲取屬性描述器
PropertyDescriptor[] pds = b.getPropertyDescriptors();
//對屬性迭代
for (PropertyDescriptor pd : pds) {
//屬性名稱
String propertyName = pd.getName();
//屬性值,用getter方法獲取
Method m = pd.getReadMethod();
Object properValue = m.invoke(bean);//用物件執行getter方法獲得屬性值
//把屬性名-屬性值 存到Map中
map.put(propertyName, properValue);
}
return map;
}
2.把Map轉化為JavaBean
思路:map轉化為javabean,不就是把map的value設定給屬性為屬性值,也就在找到bean中和Map中key相同的屬性名,把這個key對應的value設定給這個屬性。在程式上表達就是,提供一個方法,傳入map物件和一個bean的Class型別,返回一個JavaBean物件。注意,這裡傳入的引數多了一個,因為肯定得用反射建立bean物件把,如果只傳入一個map物件,怎麼建立物件?怎麼知道吧map轉化為什麼型別的JavaBean。好了,直接擼程式碼:
//把Map轉化為JavaBean
public static <T> T map2bean(Map<String,Object> map,Class<T> clz) throws Exception{
//建立一個需要轉換為的型別的物件
T obj = clz.newInstance();
//從Map中獲取和屬性名稱一樣的值,把值設定給物件(setter方法)
//得到屬性的描述器
BeanInfo b = Introspector.getBeanInfo(clz,Object.class);
PropertyDescriptor[] pds = b.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
//得到屬性的setter方法
Method setter = pd.getWriteMethod();
//得到key名字和屬性名字相同的value設定給屬性
setter.invoke(obj, map.get(pd.getName()));
}
return obj;
}