java 反射最简单的来说就是获取类所包含的注释,方法,属性,值等。我们可以用她来实现复制,转map,通过反射来打印日志等。
我们先创建两个实体类 user继承BaseEntity 类
@Data
public class User extends BaseEntity{
/**
* id
*/
public Integer id;
/**
* 姓名
*/
public String name;
/**
* 用户code
*/
public String userCode;
/**
* 用户账号
*/
public String account;
/**
* 用户年龄
*/
private Integer age;
}
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @author 29027
*/
@Data
public class BaseEntity {
/**
* 创建用户
*/
public Long createUser;
/**
* 创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date createTime;
/**
* 更新时间
*/
Long updateUser;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 状态
*/
private Integer status;
/**
* 是否删除
*/
private Integer isDeleted;
/**
* 租户
*/
private String tenantId;
/**
* 版本号
*/
private Long version;
}
创建我们的第一个方法
/**
* 获取属性名和属性值
*/
public static void getsThePropertyNameAndPropertyValue() throws IllegalAccessException {
User user = new User();
user.setName("曹操");
user.setAccount("123456789");
user.setAge(12);
/**
* 这包括公共、受保护、默认(包)访问和私有字段,但不包括继承的字段。
* */
Field[] declaredFields1 = new User().getClass().getDeclaredFields();
for (Field field : declaredFields1) {
/**
* 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
* 值为 false 则指示反射的对象应该实施 Java 语言访问检查
* 简单的来说为true则可以获取私有类的值,提高反射的效率,为false则不能
* */
field.setAccessible(true);
/**
* field.getName() 返回此 Field 对象所表示的字段的名称
* 返回指定对象的value值 我指定的user
* */
System.out.println(field.getName()+field.get(user));
}
}
输出的结果 这样就可以获取到属性名和所对应的value 值
但如果要获取继承的类的怎么办 别着急也有办法
第一种使用 getFields()方法但只能获取到公共方法不能获取到私有方法
/**
* 获取属性名和属性值
*/
public static void getsThePropertyNameAndPropertyValue2() throws IllegalAccessException {
User user = new User();
user.setName("刘备");
user.setAccount("987654321");
user.setAge(11);
user.setIsDeleted(0);
/**
* 获取这个类的所有公共方法 包含继承字段 只能获取公共字段 公共字段
* */
Field[] fields = User.class.getFields();
for (Field field : fields) {
/**
* field.getName() 返回此 Field 对象所表示的字段的名称
* 返回指定对象的value值 我指定的user
* */
System.out.println(field.getName()+field.get(user));
}
}
输出结果
如果要获取私有属性和继承的这么办我们要用另一种方法
public static void getsThePropertyNameAndPropertyValue3() throws IllegalAccessException {
User user = new User();
user.setName("孙权");
user.setAccount("09871234");
user.setAge(6);
user.setIsDeleted(0);
Integer i = 0;
Class<?> superclass = user.getClass();
/**
* 这包括公共、受保护、默认(包)访问和私有字段,但不包括继承的字段。
* */
Field[] declaredFields1 = superclass.getDeclaredFields();
do {
System.out.println(declaredFields1.length);
for (Field field : declaredFields1) {
field.setAccessible(true);
/**
* field.getName() 返回此 Field 对象所表示的字段的名称
* 返回指定对象的value值 我指定的user
* */
System.out.println(field.getName() + field.get(user));
}
/**
* 获取继承类
* */
superclass = superclass.getSuperclass();
/**
* 这包括公共、受保护、默认(包)访问和私有字段,但不包括继承的字段。
* */
declaredFields1 = superclass.getDeclaredFields();
//判断这个是因为所有类都继承了Object的类 Object是所有类的父类
} while (!"java.lang.Object".equals(superclass.getName()));
}
反射获取方法
/**
* 返回反射的的所有方法
*/
public static void method() {
Method[] declaredMethods = User.class.getDeclaredMethods();
System.out.println("不包含继承的,包含公共和私有的");
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName());
}
System.out.println("包含继承的,不包含私有的");
Method[] methods = User.class.getMethods();
for (Method declaredMethod : methods) {
System.out.println(declaredMethod.getName());
}
}
结果因为文字多 就以文本的形式发
不包含继承的,包含公共和私有的
equals
toString
hashCode
getName
getId
setName
setId
setAccount
getUserCode
setUserCode
setAge
canEqual
getAccount
getAge
包含继承的,不包含私有的
equals
toString
hashCode
getName
getId
setName
setId
setAccount
getUserCode
setUserCode
setAge
getAccount
getAge
setIsDeleted
setTenantId
getStatus
getCreateTime
getCreateUser
setCreateTime
getVersion
getIsDeleted
getUpdateTime
getTenantId
setStatus
setVersion
setUpdateUser
getUpdateUser
setUpdateTime
setCreateUser
wait
wait
wait
getClass
notify
notifyAll
反射还有很多种形式的在次此就不一一举例了 说一下反射常见的应用实体类转map ,map转实体类 ,复制类在此就举这三个例子,当然属于不太完美,只能拷贝公共类,我们可以根据上面的资料进行整个,整个日后有时间会吧他更具完善
/**
* 实体类拷贝
* EntityUtil.copy(user,new NsPrice())
*
* @param source 被复制的实体类
* @param clazz 复制的实体类
* @return 结果 clazz
*/
public static <T> T copy(Object source, T clazz) {
Field[] fields = source.getClass().getFields();
Field[] fields1 = clazz.getClass().getFields();
System.out.println(fields1.length);
for (Field field : fields) {
for (Field field1 : fields1) {
//比较类的名称和类型是否一直,如果一直则对类进行赋值
if (field.getName().equals(field1.getName())
&& field.getGenericType().equals(field1.getGenericType())) {
try {
field1.set(clazz, field.get(source));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return clazz;
}
/**
* 实体对象转成Map
*
* @param obj 实体对象
* @return
*/
public static Map<String, Object> toMap(Object obj) {
Map<String, Object> map = new HashMap<>();
if (obj == null) {
return map;
}
Class clazz = obj.getClass();
Field[] fields = clazz.getFields();
try {
for (Field field : fields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/**
* Map转成实体对象
*
* @param map 实体对象包含属性
* @param clazz 实体对象类型
* @return
*/
public static Object toEntityClass(Map<String, Object> map, Class<?> clazz) {
if (map == null) {
return null;
}
Object obj = null;
try {
obj = clazz.newInstance();
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
continue;
}
field.setAccessible(true);
field.set(obj, map.get(field.getName()));
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}