【JavaSE】反射

本文详细阐述了Java代码的生命周期,包括源代码阶段、Class类对象阶段和RunTime运行时阶段。重点介绍了反射的概念,以及如何在运行时动态获取类信息、创建对象,包括Class.forName的不同用法和Class对象的功能。通过实际案例展示了如何使用反射在框架中动态创建对象并执行方法。
摘要由CSDN通过智能技术生成

Java代码的生命周期

Java代码在计算机中经历的阶段:Source源代码阶段、Class类对象阶段、RunTime运行时阶段。

Source源代码阶段: 这个阶段是由程序员编写生成源代码,再由Javac编译器生成class文件。

Class类对象阶段:由类加载器将class文件加载到JVM内存中,并对class文件进行解析生成Class对象。

Runtime运行时阶段:由class对象创建对应的类对象。

反射的概念

正射与反射

正射:一般情况下,我们创建对象时就知道需要创建什么类,所以直接new一个对应类型的对象。

Car car = new Car();

反射:在创建对象时,并不知道对象类型。需要一定的手段(下文中获取class对象的方式)去找到其类型,再将该类型分装成class对象,class对象根据找到的类型再去创建对应类型的对象。

分析Java代码的阶段时,ClassLoader将class文件加载到内存,并且创建class对象,将原本class文件的各个部分都封装成对象。后面在运行时通过class对象及其内部的其他对象去生成最后程序真正所需要的对象。这个过程就是反射。

总结

正射是先创建对象,再访问类信息。

反射是获取信息,再创建对象。

反射的优点

1.可以在程序运行的过程中,动态的获取类信息,并进行操作。比较灵活。

比如Idea的提示功能,Idea之所以能够提示类中的各种信息,就是通过反射获取到了类信息。

2.可实现解耦,增强程序的可扩展性。

通过反射机制,可以动态的获取类信息,并进行操作。在庞大的项目中,面对复杂的需求,利用反射机制可以做到不修改源代码的情况下,就可以实现不同的功能。

比如启动Tomcat服务器时,用户修改了配置文件中的端口号,那么服务器就可以使用用户指定的端口号。这就是将配置文件与Tomcat程序进行解耦。

反射的使用过程

1.查找类信息。

类信息可以是字节码文件、加载到内存中的类信息(解析了字节码文件之后的信息)、对象(对象中包含着类的详细信息)。

2.根据类信息创建Class对象。

3.通过Class对象动态的获取类信息,甚至操作类信息。

Class对象的获取方式

使用反射的核心就是获取到Class对象。Java是面向对象的编程语言,反射根据类信息创建Class对象,而想要动态的将类信息获取出来就属于Class对象的职能了。

1.Class.forName(String className)

这种方式是通过Class类获取的。

这种方式是在Source源代码阶段,根据className找到对应的class文件,在文件中获取到类信息,将其信息的各个组成部分封装成对象。

类的各个组成部分:成员变量、成员方法、构造器、静态资源等。

使用场景:多用于读取配置文件来加载类信息,可以将类名在文件中进行配置。

2.类名.class

这种方式是通过类名的属性来获取的。

这种方式是在Class类对象阶段,根据已经记载到内存中的类信息就能知道类名,再根据类名的class属性获取Class对象。

使用场景:多用于参数传递。

3.对象名.getClass()

这种方式是根据对象的getClass()方法获取的,getClass()方法是Object提供的。

这种方式是在Runtime运行时阶段,根据已经存在的对象实例来获取其Class对象。

使用场景:多用于通过对象来获取字节码的方式。

扩展:不管使用哪一种方式获取class对象,都是同一个对象。

因为字节码文件(*.class)在程序运行过程中只会被加载一次,只会创建一个class对象。

结论验证:

//获取class对象的方法
public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
​
        //1.Class.forName(String className)
        Class clazz1 = Class.forName("reflectdemo1.Car");
​
        //2.类名.class
        Class clazz2 = Car.class;
​
        //3.对象名.getClass()
        Class clazz3 = new Car().getClass();
​
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz3 == clazz2);
        System.out.println(clazz1 == clazz3);
​
    }
}
​
输出:
true
true
true

Class对象的功能

Class对象可以让我们获取类的所有信息,包括但不限于类中定义的成员方法、成员变量、静态资源、所属包等等。接下来介绍一下Class的API(主要的)。

1.获取成员变们

Field[] getFields()

Field getField(String name)

Field[] getDeclaredFields()

Field getDeclaredField(String name)

2.获取构造方法们

Constkuctor<?>[] getConstructors()

Constructor<T> getConstructor(Class<?>... parameterTypes)

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) Constructor<?>[] getDeclaredconstructors()

3.获取成员方法们

Method[] getMethods()

Method getMethod(String name, 类<?>... parameterTypes)

Method[] getDeclaredMethods()

Method getDeclaredMethod(string name, 类<?>... parameterTypes)

4.获取类名

string getName()

获取到对应的信息可以在根据其API进行操作。

反射使用案例

需求:实现一个框架,使其能够动态的创建指定类型的对象并执行指定类型的方法。

代码实现:

//框架:动态的创建对象,并执行相应的方法;
public class Test {
    public static void main(String[] args) throws Exception {
        //1.读取配置文件
        //1.1创建Properties对象
        Properties properties = new Properties();
        //1.2读取class目录下的配置文件
        ClassLoader classLoader = Test.class.getClassLoader();
        //1.3获取配置文件的输入流
        InputStream is = classLoader.getResourceAsStream("application.properties");
        //1.4将配置文件加载到properties中
        properties.load(is);
        //1.5读取配置文件中的内容
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
​
        //2.获取需加载类的Class对象
        Class<?> cls = Class.forName(className);
​
        //3.创建对象
        Object obj = cls.newInstance();
​
        //4.执行方法
        //4.1获取需要执行的方法
        Method method = cls.getDeclaredMethod(methodName);
        method.invoke(obj);
​
    }
}

框架中读取的application.properties配置文件如下:

className = model.Student
methodName = sleep

运行结果:

sleep....
  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值