java 反射 (一)

时间:2022-01-03 22:55:17
原文地址https://www.zhihu.com/question/24304289
 
首先我们了解一下JVM,什么是JVM,Java的虚拟机,java之所以能跨平台就是因为这个东西,你可以理解成一个进程,程序,只不过他的作用是用来跑你的代码的。上图是java的内存模型,我们关注的点,一个方法区,一个栈,一个堆,初学的时候老师不深入的话只告诉你java的内存分为堆和栈,易懂点吧!

java 反射 (一)

作者:老顽童周伯通
链接:https://www.zhihu.com/question/24304289/answer/147529485
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

假如你写了一段代码:Object o=new Object();

运行了起来!

首先JVM会启动,你的代码会编译成一个.class文件,然后被类加载器加载进jvm的内存中,你的类Object加载到方法区中,创建了Object类的class对象到堆中,注意这个不是new出来的对象,而是类的类型对象,每个类只有一个class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否加载,寻找类对应的class对象,若加载好,则为你的对象分配内存,初始化也就是代码:new Object()。

上面的流程就是你自己写好的代码扔给jvm去跑,跑完就over了,jvm关闭,你的程序也停止了。

为什么要讲这个呢?因为要理解反射必须知道它在什么场景下使用。

题主想想上面的程序对象是自己new的,程序相当于写死了给jvm去跑。假如一个服务器上突然遇到某个请求哦要用到某个类,哎呀但没加载进jvm,是不是要停下来自己写段代码,new一下,哦启动一下服务器,(脑残)!

反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName("com.java.dbtest.TestConnection");通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!举多个例子,大家如果接触过spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。

========================================================================================================================

========================================================================================================================

作者:meepo
链接:https://www.zhihu.com/question/24304289/answer/150310001
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

鉴于手机知乎上看代码格式会乱掉,所以代码都截图

1. 首先准备两个很简单的业务类

java 反射 (一)

<img src="https://pic1.zhimg.com/50/v2-4410be8aedf7a91db4350ca4e9b89e6c_hd.jpg" data-rawwidth="496" data-rawheight="202" class="origin_image zh-lightbox-thumb" width="496" data-original="https://pic1.zhimg.com/v2-4410be8aedf7a91db4350ca4e9b89e6c_r.jpg">java 反射 (一)

2. 非反射方式切换不同的业务方法调用

java 反射 (一)

当需要从第一个业务方法切换到第二个业务方法的时候,使用非反射方式,必须修改代码,并且重新编译运行,才可以达到效果

3. 反射方式

使用反射方式,首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。 里面存放的是类的名称,和要调用的方法名。
在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。

当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。

<img src="https://pic1.zhimg.com/50/v2-77ffdf1131e3cf1cfea3c48aac79f951_hd.jpg" data-rawwidth="346" data-rawheight="144" class="content_image" width="346">java 反射 (一)
<img src="https://pic1.zhimg.com/50/v2-80cd1a6134c5e5c051807ddb949e9282_hd.jpg" data-rawwidth="884" data-rawheight="678" class="origin_image zh-lightbox-thumb" width="884" data-original="https://pic1.zhimg.com/v2-80cd1a6134c5e5c051807ddb949e9282_r.jpg">java 反射 (一)

========================================================================================================================

========================================================================================================================

作者:郭无心
链接:https://www.zhihu.com/question/24304289/answer/76541818
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

反射机制:所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。

下面具体介绍一下java的反射机制。

Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;

其中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组 成部分。

Java反射的作用:

在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。

Java 反射机制主要提供了以下功能

在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法

反射的常用类和函数:Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method;

其中class代表的是类对象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象,通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class类中针对这三个元素的方法:

1、得到构造器的方法


Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数, Constructor[] getConstructors() -- 获得类的所有公共构造函数 Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关) Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

2、获得字段信息的方法

Field getField(String name) -- 获得命名的公共字段 

Field[] getFields() -- 获得类的所有公共字段 

Field getDeclaredField(String name) -- 获得类声明的命名的字段 

Field[] getDeclaredFields() -- 获得类声明的所有字段

3、获得方法信息的方法

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法 

Method[] getMethods() -- 获得类的所有公共方法 

Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法 

Method[] getDeclaredMethods() -- 获得类声明的所有方法

在程序开发中使用反射并结合属性文件,可以达到程序代码与配置文件相分离的目的

如果我们想要得到对象的信息,一般需要“引入需要的‘包.类’的名称——通过new实例化——取得实例化对象”这样的过程。使用反射就可以变成“实例化对象——getClass()方法——得到完整的‘包.类’名称”这样的过程。

正常方法是通过一个类创建对象,反射方法就是通过一个对象找到一个类的信息。

========================================================================================================================

========================================================================================================================

1,Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;

其中class代表类对象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组 成部分。

2,通过对象获取类Class c =对象.getClass()------->获取类的属性方法Method method[]=c.getMethods(),可以不用通过这个类的实例对象来执行方法

3,静态加载是在编译的就会进行加载------静态加载的话就需要把软件全部卸载再重新编译安装
动态加载就是在运行时才进行加载-------动态加载,只需把软件更新的部分进行重新的编译 4,将可能需要切换改变的类/数据存放在配置文件里面,得到配置文件里面的类名称---->获取类的属性方法
Properties p = new Properties(); p.load(fis); //通过key获得value
String name= p.getProperty("className"); //通过反射机制创建对象
Class c =Class.forName(name);
Object o = c.newInstance();
配置文件(className.properties) 里面的内容是className=java.util.Date