学了一段时间Java了,但是还是很菜,看到反射这一节的时候,就有点厌烦,看不下去了,过了一段时间后我又翻了回来,因为要学习后面的,所以反射和注解这一块一定得搞明白,找了很多资料,以下是自己的总结,结合了很多大佬的东西。
1.什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
反射就是把java类中的各种成分映射成一个个的Java对象。例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)如图是类的正常加载过程:反射的原理在与class对象。熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
Java反射机制主要提供的功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时调用任意一个对象的方法
看了解释还是很模糊,那我们先了解一下其他的,什么是类对象?
在理解类对象之前,先说说我们熟悉的对象之间的区别:亚索和盲僧都是一个英雄对象,他们的区别在于各自有不同的名称,技能,血量。
然后说说类之间的区别,Hero和Item都是类,他们得区别在于有不同的方法,不同的属性。
类对象,就是用来描述这种类,都有什么属性,什么方法的。所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
2.获取类对象
1.与传统的通过new 来获取对象的方式不同
反射机制,会先拿到Hero的“类对象”,然后通过类对象获取“构造器对象”
再通过构造器对象创建一个对象
2.获取类对象有3种方式
1. Class.forName
2. Hero.class
3. new Hero().getClass()
看到这里可能只是对类对象概念有了些理解,但具体的反射使用可以参考这篇大佬的博客对反射的操作会有更深的理解
3.最后我简单说一下反射有什么用
反射非常强大,但是学习了之后,会不知道该如何使用,反而觉得还不如直接调用方法来的直接和方便。
通常来说,需要在学习了Spring 的依赖注入,反转控制之后,才会对反射有更好的理解,但是刚学到这里的同学,不一定接触了Spring,所以在这里举两个例子,来演示一下反射的一种实际运用。
1.首先准备两个类 Service1.Java
package Reflect.fanshe;
public class Service1 {
public void doService1(){
System.out.println("业务方法1");
}
}
和Service2.Java
package Reflect.fanshe;
public class Service2 {
public void doService2(){
System.out.println("业务方法2");
}
}
2.若是用非反射方法从第一个业务切换到第二个业务,必须修改代码,并且重新编译运行,才可以达到效果
package reflection;
public class Test {
public static void main(String[] args) {
// new Service1().doService1();
new Service2().doService2();
}
}
3.使用反射方法
使用反射方式,首先准备一个配置文件,就叫做spring.txt吧, 放在file目录下。 里面存放的是类的名称,和要调用的方法名。
在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。
当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。
这也是Spring框架的最基本的原理,只是它做的更丰富,安全,健壮。
package Reflect.fanshe;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test {
@SuppressWarnings({"rawtypes","unchecked"})
public static void main(String[] args) throws Exception{
File f = new File("E:/file/LOL/spring.txt");
Properties scf = new Properties();
scf.load(new FileInputStream(f));
String className = (String) scf.get("class");
String methodName = (String)scf.get("method");
//根据类名获取对象
Class cla = Class.forName(className);
//根据方法名称,获取方法对象
Method m = cla.getMethod(methodName);
//获取构造器
Constructor c = cla.getConstructor();
//根据构造器,实例化出对象
Object service = c.newInstance();
//调用对象的指定方法
m.invoke(service);
}
}
结果