1. 什么是反射? 2. 获取反射类Class? 3. 通过反射类获取Field对象 4. 通过反射类获取Method类 5. 通过反射类获取Annotation类 6. 通过反射类获取Contstructor类 7. 综合练习 8. 通过反射+注解+泛型手写一个ORM框架。
框架: 是一个半成品软件。好处: 可以快速开发程序,使开发变的更加简洁。
反射: 把类中的成员封装成其他的类的过程。这就是反射。
(1)通过全类名字符串来获取。
比如框架. spring框架 <bean id="student" class="com.ykq.entity.Student"> ----得到该类的对象
(2)通过类名来获取。
比如:mybatis-----> session.getMapper(StudentDao.class);----StudentDao对象
(3)通过对象来获取。
如果知道了类对象,则可以通过该对象获取Class
**/ public class Test01 { public static void main(String[] args) throws Exception{ //如何获取Class类 //(1)通过全类名来获取. Class<?> aClass = Class.forName("com.ykq.demo01.Student"); //(2)通过类名获取. Class<?> bClass = Student.class; //(3)通过对象来获取Class类 Student s=new Student(); Class<?> cClass = s.getClass(); //思考 aClass,bClass,cClass这三个对象的引用地址是否相同? System.out.println(aClass==bClass); System.out.println(aClass==cClass); System.out.println(bClass==cClass);//任意一个类,经过加载到JVM中只会产生一个Class类对象。 } }
Class<?> aclass=Class.forName("com.ykq.demo01.Student"); //得到对应的类对象 Object o = aclass.newInstance(); //可以通过反射类得到相应的类对象 原理就是调用的无参构造函数。 System.out.println(o);
getField(String name) : 获取指定属性名的public属性对象。 getFields() : 获取所有的public属性对象 包含父类中的属性。 getDeclaredField(String name) :获取指定的属性类对象。不能获取父类的属性。 getDeclaredFields() : 获取所有的属性类对象。不包含父类的属性。
//通过反射类获取Field类对象。 package com.ykq.demo02; import java.lang.reflect.Field; /** * @program: java高级特点-反射 * @description: * @author: 闫克起 * @create: 2021-08-09 15:20 **/ public class Test02 { public static void main(String[] args)throws Exception { Class clazz=Student.class; Field ageField= clazz.getField("address");//获取Student类中的public修饰age属性类对象。以及父类中的属性。 //System.out.println(ageField); Field[] fields = clazz.getFields();//获取类中所有public修饰的属性类对象 以及父类中的类对象. // for (Field field:fields){ // System.out.println(field); // } Field age = clazz.getDeclaredField("name");//获取指定属性名的属性对象。不包含父类中的属性 // System.out.println(age); Field[] declaredFields = clazz.getDeclaredFields(); //获取所有的奔雷中定义的属性对象 for(Field field:declaredFields){ System.out.println(field); } } } class Father{ public String address; } class Student extends Father{//----编译后产生几个字节码 1个----->classLoader加载到JVM中 private String name; public Integer age; String school; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } public void show(){ System.out.println("show方法的name==="+name+";age==="+age); } public Student(){ System.out.println("这是无参构造函数"); } }
get(Object obj) : 获取该属性的值。 set(Object obj, Object value) : 为该属性设置值。 setAccessible(true):表示允许访问私有属性。
public static void main(String[] args) throws Exception { Class clazz=Student.class; Object o = clazz.newInstance();//通过反射类得到相应的类对象 Field ageField = clazz.getField("age");//通过反射类得到相应的public修饰的属性对象 Object ageValue = ageField.get(o);//得到对象o中age属性的值 System.out.println(ageValue); System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); ageField.set(o,25);//为age属性赋值 ageValue= ageField.get(o); System.out.println(ageValue); System.out.println("==============================================="); Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true);//设置该属性可以被访问 nameField.set(o,"范银成"); //为私有属性赋值。 Object nameValue = nameField.get(o); System.out.println(nameValue); }
getMethod(String name, 类<?>... parameterTypes) :得到指定名称和形参类型的方法。 getMethods() :得到所有的public修饰方法。
public static void main(String[] args) throws Exception { Class clazz=Class.forName("com.ykq.demo03.Student"); Object o = clazz.newInstance(); Method show = clazz.getMethod("show");//获取无参的show方法对象 show.invoke(o);//回调 Method类中的方法 Method setName=clazz.getMethod("setName",String.class);//获取有参的setName, 参数的数据类型 setName.invoke(o,"海涛");//执行该方法 Method[] methods = clazz.getMethods();//得到所有的public修饰的方法 包含父类中的 for (Method m:methods){ System.out.println(m); } }
getAnnotation():获取指定的注解 getAnnotations():获取所有的类注解
package com.ykq.demo04; import java.lang.annotation.*; import java.lang.reflect.Field; /** * @program: java高级特点-反射 * @description: * @author: 闫克起 * @create: 2021-08-09 16:47 **/ public class Test04 { public static void main(String[] args) throws Exception{ Class clazz=Student.class; MyAnnotation annotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);//获取Student类上的MyAnnotation注解 System.out.println(annotation.value());//得到注解相应的属性值。 //1.得到Field对象 Field stuId = clazz.getDeclaredField("stuId"); TableId annotation1 = stuId.getAnnotation(TableId.class); System.out.println(annotation1.value()); //2.得到Method上的注解 省略 } } @MyAnnotation(value = "tb_student") class Student{ @TableId(value = "stu_id") private Integer stuId; /* * 回顾: * @Controller * class StudentController{ * @Autowire * private StudentService studentService; * @RequestMapping(value="list") * public String list(){ * * } * } * */ } @Target(value = ElementType.TYPE) @Retention(value= RetentionPolicy.RUNTIME) //指定注解的有效期 默认源码有效 @interface MyAnnotation{ //自定义注解 String value(); } @Target(value = ElementType.FIELD) @Retention(value= RetentionPolicy.RUNTIME) //指定注解的有效期 默认源码有效 @interface TableId{ String value(); }
1.写一个框架,不改变任何类的前提下,可以帮我们创建任意类的对象,执行该类下面的方法;
条件: 反射+属性配置文件。
步骤:
读取配置文件中的全类名。
//1.读取配置文件 InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("config.properties");//读取配置文件 //2.读取配置文件的内容 =====把属性文件中的内容封装到Properties类中 Properties properties=new Properties(); properties.load(resourceAsStream);
根据该名创建反射类
根据反射类创建该类的对象。
读取配置文件中的方法名
根据反射类得到方法对象
执行该方法。
总结:
1. 反射:======>Class 反射属性=====>Field: 反射方法=====>Method: 反射注解=====>Annotation:
(1)作业:
(1)把上课讲的例子 全部写一遍。【2遍】
(2) 熟悉手写的ORM框架