Java动态处理类常用方法
一、简介
工作中经常会遇到动态处理类及属性的场景,在此处记录下常用方法。
1、依赖的jar
部分样例方法依赖的jar有:
- Apache Commons BeanUtils
或使用Maven:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
- Apache Commons Logging
2、模型类
样例使用到的模型相关类有:
Animal:
public class Animal {
private String id;
private String name;
private List<Animal> children = new ArrayList<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Animal> getChildren() {
return children;
}
public void setChildren(List<Animal> children) {
this.children = children;
}
}
Mammal:
public class Mammal extends Animal{
private Nest nest;
private boolean male;
public Nest getNest() {
return nest;
}
public void setNest(Nest nest) {
this.nest = nest;
}
public boolean isMale() {
return male;
}
public void setMale(boolean male) {
this.male = male;
}
}
Nest:
public class Nest {
private int size;
private String color;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
Dog:
public class Dog extends Mammal{
private Map<String, Animal> friends = new HashMap<>();
public Map<String, Animal> getFriends() {
return friends;
}
public void setFriends(Map<String, Animal> friends) {
this.friends = friends;
}
}
二、常用方法
1、判断对象是否可读写某个属性
- 方法定义:
PropertyUtils.isReadable(Object bean, String name)
PropertyUtils.isWriteable(Object bean, String name)
- 样例:
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(PropertyUtils.isReadable(dog, "id"));
System.out.println(PropertyUtils.isWriteable(dog, "name"));
}
- 输出:
true
true
2、对象普通属性的赋值与取值
- 方法定义:
设置指定bean的某个属性的值:
PropertyUtils.setProperty(Object bean, String name, Object value)
设置指定bean的某个(可能是嵌套的)属性的值:
PropertyUtils.setNestedProperty(Object bean, String name, Object value)
返回指定bean的某个属性的值:
PropertyUtils.getProperty(Object bean, String name)
返回指定bean的某个(可能是嵌套的)属性的值:
PropertyUtils.getNestedProperty(Object bean, String name)
- 样例:
public static void main(String[] args) {
try {
Dog dog = new Dog();
Nest nest = new Nest();
dog.setNest(nest);
PropertyUtils.setProperty(dog, "id", "007");
PropertyUtils.setNestedProperty(dog, "nest.color", "pink");
PropertyUtils.setProperty(dog, "name", "super dog");
System.out.println(PropertyUtils.getProperty(dog, "id"));
System.out.println(PropertyUtils.getNestedProperty(dog, "nest.color"));
System.out.println(PropertyUtils.getNestedProperty(dog, "name"));
} catch (Exception e) {
e.printStackTrace();
}
}
- 输出:
007
pink
super dog
3、对象集合属性的赋值与取值
- 方法定义:
获取指定bean的Map属性某个key的值:
PropertyUtils.getMappedProperty(Object bean, String name, String key)
设置指定bean的Map属性某个key的值:
PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)
获取指定bean的List属性指定索引位置元素的值:
PropertyUtils.getIndexedProperty(Object bean, String name, int index)
设置指定bean的List属性指定索引位置元素的值:
PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)
- Map样例
public static void main(String[] args) {
try{
String field = "friends";
Dog dog = new Dog();
dog.setName("Tom");
Dog abel = new Dog();
abel.setName("Abel");
dog.getFriends().put(abel.getName(), abel);
Dog ben = new Dog();
ben.setName("Ben");
PropertyUtils.setMappedProperty(dog, field, "AAA", ben);
Dog friend = (Dog) PropertyUtils.getMappedProperty(dog, field, "Abel");
System.out.println(friend.getName());
friend = (Dog) PropertyUtils.getMappedProperty(dog, field, "AAA");
System.out.println(friend.getName());
}catch(Exception e){
e.printStackTrace();
}
}
输出:
Abel
Ben
- List样例
public static void main(String[] args) {
try{
String field = "children";
Dog dog = new Dog();
dog.setName("Tom");
dog.getChildren().add(null);
dog.getChildren().add(null);
Dog one = new Dog();
one.setName("a child");
Dog another = new Dog();
another.setName("another child");
PropertyUtils.setIndexedProperty(dog, field, 0, one);
PropertyUtils.setIndexedProperty(dog, field, 1, another);
Dog child = (Dog) PropertyUtils.getIndexedProperty(dog, field, 0);
System.out.println(child.getName());
child = (Dog) PropertyUtils.getIndexedProperty(dog, field, 1);
System.out.println(child.getName());
}catch(Exception e){
e.printStackTrace();
}
}
输出:
a child
another child
4、获取某个类或对象的属性描述符
- 方法定义:
PropertyUtils.getPropertyDescriptors(Class<?> beanClass)
PropertyUtils.getPropertyDescriptors(Object bean)
- 样例:
public static void main(String[] args) {
PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(Dog.class);
for(PropertyDescriptor descriptor : descriptors){
System.out.println(String.format("%s\t%s", descriptor.getName(), descriptor.getPropertyType()));
}
}
- 输出:
children interface java.util.List
name class java.lang.String
id class java.lang.String
nest class com.bean.model.Nest
class class java.lang.Class
friends interface java.util.Map
male boolean
5、获取某个类的所有字段
与上面类似,下面的方法也支持获取继承的属性:
public static List<Field> getFields(Class<?> clazz){
List<Field> fields = new ArrayList<>();
while(clazz != null){
Field[] declaredFields = clazz.getDeclaredFields();
for(Field field : declaredFields){
//过滤掉static属性
if(Modifier.isStatic(field.getModifiers())){
continue;
}
fields.add(field);
}
clazz = clazz.getSuperclass();
}
return fields;
}
- 测试方法:
public static void main(String[] args) {
List<Field> fields = getFields(Dog.class);
for(Field field : fields){
System.out.println(String.format("%s\t%s", field.getName(), field.getType()));
}
}
- 输出:
friends interface java.util.Map
nest class com.bean.model.Nest
male boolean
id class java.lang.String
name class java.lang.String
children interface java.util.List
6、获取集合元素的类型
public static Class<?> getListItemClass(Class<?> clazz, String property) {
try {
Field field = clazz.getDeclaredField(property);
Type genericType = field.getGenericType();
if(genericType instanceof ParameterizedType){
ParameterizedType itemType = (ParameterizedType) genericType;
Class<?> itemClass = (Class<?>) itemType.getActualTypeArguments()[0];
return itemClass;
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
- 测试方法:
private static void test03() {
Class<?> itemClass = getListItemClass(Animal.class, "children");
System.out.println(itemClass);
}
- 输出:
class com.bean.model.Animal
7、动态创建集合及元素
- 样例
public static void main(String[] args) {
try {
//动态创建对象
Animal animal = Animal.class.newInstance();
PropertyUtils.setProperty(animal, "id", "001");
PropertyUtils.setProperty(animal, "name", "Tom");
//动态创建集合
List<Object> children = ArrayList.class.newInstance();
PropertyUtils.setProperty(animal, "children", children);
Class<?> itemType = getListItemClass(Animal.class, "children");
//创建集合元素
Object child = itemType.newInstance();
PropertyUtils.setProperty(child, "name", "Tom's baby");
children.add(child);
System.out.println(String.format("ID: %s, Name: %s", animal.getId(), animal.getName()));
for(Animal item : animal.getChildren()){
System.out.println("Child Name: " + item.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
- 输出:
ID: 001, Name: Tom
Child Name: Tom's baby