Java反射机制

反射引入?

(1)MyBatis如何做到给一个类型就可以把数据封装到这个类型的对象中去?

UserMapper文件中:

<select id="findUserById" parameterType="int" resultType="com.model.User">
<select id="findGradeById" parameterType="int" resultType="com.model.Grade">

(2)Servlet 中web.xml 配置:

<servlet>    
    <servlet-name>login</servlet-name>   
    <servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>

(3)使用jdbc连接MySql数据库:

Class.forName("com.mysql.cj.jdbc.Driver");

注:框架的底层肯定是可以做到写一套代码,就可以对任何的类进行操作。

在这里,我们可以使用反射机制进行实现。

通过反射机制,来明白框架的底层原理是什么?

在之前,在java中是如何进行使用的一个类的?

class User{

}

User u = new User(); 对于我们的使用没有问题,因为我们知道项目中有哪些类。(因为我们自己进行创建类,然后使用类)

但是,我们在使用框架的时候,框架是事先不知道是哪个类的,在运行的时候(通过类的地址)才知道是哪个类,(框架不能直接进行创建对象 new 对象

框架运行时,才会读取(解析)xml文件,才知道具体是哪个类,而且这个类可以是任意的。框架如何处理?

在运行时框架会创建该类的对象。

框架时如何做到的?

使用java中的反射机制。

什么是反射机制?

java反射机制,是在运行时,对于任意一个类(联想到框架可以处理任何类),都能够知道这个类中所有的信息(属性、方法、代码块等) 。可以创建此类的对象,并调用此类中的方法,这种动态获取类中信息,动态调用对象中的方法的功能,称为java的反射机制。

例:resultType="com.dao.Grade" : "com.dao.Grade" 只是一个字符串,但是这个字符串是类的地址,类中存放类的信息。

正向使用

User u = new User();  知道有这个类,才进行创建对象

反向使用

反射其实就是一种反向对类的使用。(通过类的地址,动态获取类的信息,动态调用)

反射是如何具体实现的?

这种动态获取类的信息,动态创建对象,动态调用方式是如何具体实现的?

实现反射机制需要用到4各类

1. Class 类型

Class类的类,表示正在运行的Java应用程序中的类和接口

Class类是实现反射机制的根基。

一旦某个类被加载,就会在内存中创建一个Class类的对象,用来封装获取类的信息,一个类只有一个Class类的对象。

  • Constructor 构造方法
  • Method 方法
  • Field 属性

注:除了Class外,其他类都位于java.lang.reflect中

创建Car类

public class Car {

     private int no;
     private int name;
     private int price;

    public Car() {
        System.out.println("无参构造方法");
    }

    public Car(int no, int name, int price) {
        this.no = no;
        this.name = name;
        this.price = price;
        System.out.println("有参构造方法");
    }

   //getter和setter略
    

    @Override
    public String toString() {
        return "Car{" +
                "no=" + no +
                ", name=" + name +
                ", price=" + price +
                '}';
    }
}

 Car car = new Car();  以前使用类,是由虚拟机加载的,过程看不见

String classpash = "com.reflect.Car"

根据类的地址,将类的字节码加载到内存中,并为此类生成它的Class类的对象

 Class c = Class.forName(classpath);

Object car = c.newInstance();

创建传递过来的类的对象

通过Class类的对象,可以获得类的信息  例如获得类中的构造方法信息

获得指定的构造方法信息,将信息封装到Constructor对象中

无参构造方法:

Constructor cons1 =  c.getConstructor(); 

有参构造方法:

Constructor cons2 =  c.getConstructor(int.class,String.class,float.class);

通过Constructor类中的newInstance()创建对象

Object object1   =   cons1.newInstance();
Object object2   =   cons2.newInstance(1,"大众",100000);

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test1 {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    
        String classpath = "com.reflect.Car";

        //根据类的地址,将类的字节码加载到内存中,并为此类生成它的Class类的对象
         Class  c =  Class.forName(classpath);


           //通过Class类的对象,可以获得类的信息  例如获得类中的构造方法信息
           Constructor cons1 =  c.getConstructor();

           Constructor cons2 =  c.getConstructor(int.class,String.class,float.class);
          //获得指定的构造方法信息,将信息封装到Constructor对象中

           Object object1   =   cons1.newInstance();
            //通过Constructor类中的newInstance()创建对象

           Object object2   =   cons2.newInstance(1,"大众",100000);

    }
}

一个Field类的对象表示类中一个属性
Field[]  fields  =  c.getDeclaredFields();         获得类中所有的属性

 for (Field f : fields){
       String fname =   f.getName();     获得是属性名
        根据属性名,生成set,get方法的名字,结合属性类型,获得对应属性的get/set方法
       Method  m = c.getMethod("set"+String.valueOf(fname.charAt(0)).toUpperCase() + fname.substring(1),f.getType());
       System.out.println(m);
       m.invoke(obj, 1);  //动态调用获得到的set方法,为动态创建的对象属性赋值
   }

public class Test2 {

    public static void main(String[] args) throws ClassNotFoundException, 

IllegalAccessException, InstantiationException,
 NoSuchMethodException, InvocationTargetException {

        //resultType="com.ffyc.demo.model.User"
        String classpath = "com.reflect.Car";

        //根据类的地址,将类的字节码加载到内存中,并为此类生成它的Class类的对象
         Class  c =  Class.forName(classpath);

            Object obj =  c.newInstance();

            //一个Field类的对象表示类中一个属性
             Field [] fields = c.getDeclaredFields();//获得类中所有的属性

             for (Field f : fields){
                    String fname =   f.getName();//获得是属性名
                 //根据属性名,生成set,get方法的名字,结合属性类型,获得对应属性的get/set方法
                 Method m = c.getMethod("set"+String.valueOf(fname.charAt(0)).toUpperCase()+fname.substring(1),f.getType());
                 System.out.println(m);
                 m.invoke(obj, 1);  //动态调用获得到的set方法,为动态创建的对象属性赋值
             }

        System.out.println(obj);


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值