2. 正文--反射

 1. 什么是反射?
 2. 获取反射类Class?
 3. 通过反射类获取Field对象
 4. 通过反射类获取Method类
 5. 通过反射类获取Annotation类
 6. 通过反射类获取Contstructor类
 7. 综合练习
 8. 通过反射+注解+泛型手写一个ORM框架。

3. 什么是反射---是框架设计的灵魂。

框架: 是一个半成品软件。好处: 可以快速开发程序,使开发变的更加简洁。

反射: 把类中的成员封装成其他的类的过程。这就是反射。

 

 

 

4. 如何获取Class反射类

(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类对象。
    }
 }

5. 通过反射类得到相应的类对象。

        Class<?> aclass=Class.forName("com.ykq.demo01.Student");
      //得到对应的类对象
      Object o = aclass.newInstance(); //可以通过反射类得到相应的类对象 原理就是调用的无参构造函数。
      System.out.println(o);

6. 得到Field类对象。

 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("这是无参构造函数");
    }
 }

6.2 Field相应操作

 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);
 
    }

7. Class得到Method的操作

 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);
        }
 
    }

8. 获取Annotation注解。--【Class,Field ,Method】

 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();
 }

 

9. 案例 --- spring bean

1.写一个框架,不改变任何类的前提下,可以帮我们创建任意类的对象,执行该类下面的方法;

条件: 反射+属性配置文件。

步骤:

  1. 读取配置文件中的全类名。

       //1.读取配置文件
      InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("config.properties");//读取配置文件
            //2.读取配置文件的内容 =====把属性文件中的内容封装到Properties类中
            Properties properties=new Properties();
            properties.load(resourceAsStream);

     

  2. 根据该名创建反射类

  3. 根据反射类创建该类的对象。

  4. 读取配置文件中的方法名

  5. 根据反射类得到方法对象

  6. 执行该方法。

 

总结:

 1. 反射:======>Class 
    反射属性=====>Field:
    反射方法=====>Method:
    反射注解=====>Annotation:  

(1)作业:

(1)把上课讲的例子 全部写一遍。【2遍】

(2) 熟悉手写的ORM框架

 

 

posted on 2021-12-18 11:01  帅哥的爸爸  阅读(333)  评论(0编辑  收藏  举报