1.利用反射完成不同参数赋值
<1>无参构造[默认赋值]
Student 和 Teacher皆为JavaBean类
public class Demo1 {public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {//创建老师对象Teacher teacher = creatInstance(Teacher.class);System.out.println(teacher);//获取学生对象Student student = creatInstance(Student.class);System.out.println(student);}//需求:写一个方法:能够创建任何类的对象,并把对象返回private static <T>T creatInstance(Class<T> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//获取空参构造【通用】Constructor<T> constructor = clazz.getDeclaredConstructor();constructor.setAccessible(true);T t = constructor.newInstance();return t;}
}打印结果:
-----------------------------------------------------------------------
public...Teacher...无参构造方法
Teacher{name='null', age=0}
public...Student...无参构造方法
Student{name='null', age=0}
<2>有参构造
public class Demo2 {public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {Student obj1 = new Student();//把Student对象的属性名和属性值,存储Map集合HashMap<String, Object> map1 = new HashMap<>();map1.put("name", "张三");map1.put("age", 20);//调用方法给Student对象的属性赋值populate(obj1, map1);Teacher obj2 = new Teacher();//把Teacher对象的属性名和属性值,存储Map集合HashMap<String, Object> map2 = new HashMap<>();map2.put("name", "李四");map2.put("age", 30);map2.put("salary", 15000);//调用方法给Teacher对象的属性赋值populate(obj2, map2);}private static void populate(Object obj, HashMap<String, Object> map) throws IllegalAccessException, NoSuchFieldException {//1.通过getClass()方法获取obj的字节码Class<?> clazz = obj.getClass();//2.获取字节码所有成员变量(包括私有的)//注意:成员变量的名称就是map集合中的每一个键Set<String> keys = map.keySet();Field[] declaredFields = clazz.getDeclaredFields();for (String key : keys) {for (int i = 0; i < declaredFields.length; i++) {Field declaredField = declaredFields[i];//3.使用暴力反射给所有的成员变量赋值//注意:成员变量的值就是map集合中键对应的值declaredField.setAccessible(true);if (key.equals(declaredField.getName())) {declaredField.set(obj, map.get(key));}}}System.out.println(obj);}
}打印结果:
------------------------------------------------------------------------
Student{name='张三', age=20}
Teacher{name='李四', age=30, salary=15000}
2.反射与XML解析
[通过改配置文件执行对应类的方法]
要求:使用Dom4j解析config.xml配置文件。然后执行Student类中的study方法
XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<config><classname>com.itheima1.Student</classname><method><!--方法的参数名称--><methodName>study</methodName><!--方法的参数类型,需要些类的全类名--><paramType>java.lang.String</paramType><!--调用方法时传递的参数值--><paramValue>Java基础课程</paramValue></method><method><!--方法的参数名称--><methodName>teach</methodName><!--方法的参数类型[引用数据类型],需要些类的全类名--><paramType>java.lang.String</paramType><!--调用方法时传递的参数值--><paramValue>Java基础课程</paramValue>
</method>
</config>
测试类
public class Demo4 {public static void main(String[] args) throws Exception {//使用Dom4j解析config.xml配置文件SAXReader saxReader = new SAXReader();Document document = saxReader.read("day17_myXml\\src\\com\\zuoye\\xml\\config.xml");//读取方法的名称,参数类型,参数值List<Element> elements = document.getRootElement().elements("method");for (Element element : elements) {//读取文件路径String classname = document.getRootElement().element("classname").getText();String method = element.element("methodName").getText();String paramType = element.element("paramType").getText();String paramValue = element.element("paramValue").getText();//反射执行Student类中的study方法Class<?> clazz = Class.forName(classname);Student student = (Student) clazz.getConstructor().newInstance();Class<?> paramTypeClazz = Class.forName(paramType);Method method1 = clazz.getMethod(method, paramTypeClazz);method1.invoke(student, paramValue);}}
}//学生类
public class Student {public void study(String s){System.out.println("学生在学习"+s);}public void teach(String s){System.out.println("老师教学生"+s);}
}打印结果:
---------------------------------------------------------
学生在学习Java基础课程
老师教学生Java基础课程
3.反射与注解
//学生类
public class Student {public void study(){System.out.println("学生在努力学习");}
}//自定义注解
@Retention(RetentionPolicy.RUNTIME) //注解在运行时期有效
@Target(ElementType.TYPE) //注解可以使用在类上
public @interface Anno {public String classname();public String methodname();//value 成员变量只有一个,则可以省略名称直接赋值
}//配置文件
@Anno(classname = "com.itheima3.Student", methodname = "study")
public class Config {
}//测试类
public class Demo {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {//加载ConfigClass<?> configClazz = Class.forName("com.itheima3.Config");//获取Anno注解的属性值Anno anno = configClazz.getAnnotation(Anno.class);String classname = anno.classname();String methodname = anno.methodname();//System.out.println(classname);//通过反射获取classname对应的字节码Class<?> clazz = Class.forName(classname);Object o = clazz.getConstructor().newInstance();//获取methodname对应的方法Method method = clazz.getMethod(methodname);//执行方法method.invoke(o);}
}打印结果:
-------------------------------------------------------------------------
学生在努力学习