概述
通过反射将俩个类对象交换
现在需求如下,需要封装一个工具类,该工具通过反射和注解将一个类的特定内容取出,赋值给另一个类。实现类的交换。
提示:通过此练习可以对反射的理解更上一层楼。
文章目录
- 通过反射将俩个类对象交换
- 一、思考
- 1. 反射的来龙去脉
- 2. 如何解决问题
- 二、过程的实现。
- 1.首先编写两个注解,用来筛选需要的值和不需要的值。
- 2. 封装工具类
- 3. 测试类,新建两个对象类和测试类,验证结果。
- 三、测试结果
一、思考
1. 反射的来龙去脉
什么是反射,反射可以做什么?
高级工程师都会亲睐反射,因为反射可以做到很多事情,甚至大幅度简化程序。
反射是Java语言的特征之一。它允许在运行时动态加载类、获取类信息、生成对象、操作对象的属性或方法等。
反射可以做到很多事情,比如
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法。甚至是private方法。
- 生成动态代理等
理解反射对一个程序员来讲是至关重要的。
2. 如何解决问题
然后思考:如何通过发射拿到一个类的所有方法,并且把一个对象中需要的值赋值给另一个对象?
这个算法核心是字段的赋值,字段哪里来,当然通过反射类调用的方法拿到了。
如果我们拿到了资源对象的字段,然后利用字段的get方法,是不是就可以把资源对象的值赋值给目标对象上。围绕此核心,我们首先要拿到资源对象的Class类对象,然后利用该类对象获取所有的描述字段的值,然后遍历所有资源对象字段的值,在其中利用注解拿到我们想拿的值,剔除我们不想要的值。然后再拿到目标对象的对象类,获取目标对象的对应资源对象字段名称的值,然后通过目标对象的get方法将值取到。
二、过程的实现。
1.首先编写两个注解,用来筛选需要的值和不需要的值。
TargetField.java
package com.lqz.test.annotation;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD})
public @interface TargetField {
String value();
}
IgnoreField.java
package com.lqz.test.annotation;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD})
public @interface IgnoreField {
}
2. 封装工具类
CopyExcutor.java
package com.lqz.test.util;
import com.lqz.test.annotation.IgnoreField;
import com.lqz.test.annotation.TargetField;
import java.lang.reflect.Field;
public class CopyExcutor {
private Object source;
private Object target;
public CopyExcutor(Object source, Object target) {
this.source = source;
this.target = target;
}
public void executor() throws IllegalAccessException {
Class<?> sourceClass = source.getClass();
Field[] sourcedeclaredFields = sourceClass.getDeclaredFields();
for (int i = 0; i < sourcedeclaredFields.length; i++) {
IgnoreField ignoreField = sourcedeclaredFields[i].getAnnotation(IgnoreField.class);
if (ignoreField!=null){
continue;
}
String targetName=null;
TargetField targetField = sourcedeclaredFields[i].getAnnotation(TargetField.class);
if (targetField==null){
targetName= sourcedeclaredFields[i].getName();//对象字段名
}else {
targetName=targetField.value();
}
Class<?> targetClass = target.getClass();
Field declaredField=null;
try {
declaredField = targetClass.getDeclaredField(targetName);
} catch (NoSuchFieldException e) {
System.out.println("没有拿到字段");
System.exit(0);
}
sourcedeclaredFields[i].setAccessible(true);
Object o = sourcedeclaredFields[i].get(source);
if (o==null){
return;
}
declaredField.setAccessible(true);
declaredField.set(target,o);
}
}
}
3. 测试类,新建两个对象类和测试类,验证结果。
Source.java
package com.lqz.test.entity;
import com.lqz.test.annotation.IgnoreField;
import com.lqz.test.annotation.TargetField;
import java.util.Date;
public class Source {
@TargetField("name")
private String Sname;
@IgnoreField
private String Snumber;
@TargetField("age")
private int age;
@TargetField("score")
private double score;
@TargetField("birthday")
private Date Sbrithday;
@IgnoreField
private String selse;
@Override
public String toString() {
return "Source{" +
"Sname='" + Sname + ''' +
", Snumber='" + Snumber + ''' +
", age=" + age +
", score=" + score +
", Sbrithday=" + Sbrithday +
", selse='" + selse + ''' +
'}';
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
public String getSnumber() {
return Snumber;
}
public void setSnumber(String snumber) {
Snumber = snumber;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public Date getSbrithday() {
return Sbrithday;
}
public void setSbrithday(Date sbrithday) {
Sbrithday = sbrithday;
}
public String getSelse() {
return selse;
}
public void setSelse(String selse) {
this.selse = selse;
}
public Source() {
}
public Source(String sname, String snumber, int age, double score, Date sbrithday, String selse) {
Sname = sname;
Snumber = snumber;
this.age = age;
this.score = score;
Sbrithday = sbrithday;
this.selse = selse;
}
}
Target.java
package com.lqz.test.entity;
import java.util.Date;
public class Target {
private String name;
private int age;
private double score;
private Date birthday;
public Target() {
}
@Override
public String toString() {
return "Target{" +
"name='" + name + ''' +
", age=" + age +
", score=" + score +
", birthday=" + birthday +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Target(String name, int age, double score, Date birthday) {
this.name = name;
this.age = age;
this.score = score;
this.birthday = birthday;
}
}
Test.java
package com.lqz.test;
import com.lqz.test.entity.Source;
import com.lqz.test.entity.Target;
import com.lqz.test.util.CopyExcutor;
import java.util.Date;
public class test {
public static void main(String[] args) {
Source source = new Source("娄黔子", "15634917785", 21, 99.9, new Date(), "其他");
Target target = new Target();
System.out.println("资源对象的内容:"+source);
System.out.println("目标对象的内容:"+target);
CopyExcutor copyExcutor = new CopyExcutor(source, target);
try {
copyExcutor.executor();
} catch (IllegalAccessException e) {
System.out.println("运行出错,请检查程序");
}
System.out.println("=====================工具方法结束============================");
System.out.println("资源对象的内容:"+source);
System.out.println("目标对象的内容:"+target);
}
}
三、测试结果
从图中我们可以看到,
资源对象中拥有的属性,“Sname,Snumber,age,score,brithday,selse”
目标对象拥有的属性,
“name,age,score,birthday”
初始给资源对象赋值:
new Source("娄黔子", "15634917785", 21, 99.9, new Date(), "其他")
目标对象为空,运行方法后
我们得到了目标对象:
Target{name='娄黔子', age=21, score=99.9, birthday=Tue Apr 27 14:52:05 CST 2021}
最后
以上就是高贵小白菜为你收集整理的通过反射将俩个类对象交换通过反射将俩个类对象交换一、思考二、过程的实现。三、测试结果的全部内容,希望文章能够帮你解决通过反射将俩个类对象交换通过反射将俩个类对象交换一、思考二、过程的实现。三、测试结果所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复