一、 什么是反射
Java的反射机制(reflection) 中是很重要的机制。在运行中状态中对于任意一个类都能知道它的属性、方法。对于任意一个类,都能够调用任意方法和属性。既然任意调用那也能改动,这种动态获取信息和动态调用方法的功能称为java的反射机制。
二、用途
1、众所周知,在实际情况下多次遇见其属性是私有,只面向系统进行开放,这时候可以用Java的反射机制来获取所需的私有成员和方法。
2、反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有类Bean交给spring容器管理,无论是xml配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就这些动态创建这些类。
三 反射基本信息
Java程序许多对象会出现两种类型:运行时类型和编译时类型,类如Person person= new Student() :这句代码中person在编译时类型为Person,运行时为Student。程序需要在运行时发现对象和类的真实信息。而通过反射程序就能判断出该类和对象属于哪些类。
反射示例
获取class对象的三种方式
在反射之前,我们需要做的第一步就是先拿到反射的类的class对象,然后通过class对象的核心方法,达到反射的目的,即:在运行时状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能够拿到就能够进行修改。
第一种,使用Class.forName(“类的全路径名”)静态方法。前提:已明确类的全路径名。
第二种, 使用 .class方法。说明:仅适合在编译前就已经明确要操作的class。
第三种, 使用类对象的getClass()方法。(这个方法需要注意在使用前要先new 一下 )
public class Student {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c1 = Class.forName("reflectiondemo.stu");
Class<?> c2 = stu.class;
stu st = new stu();这是第三种方法
Class<?> c3 = st.getClass();
}
class类(反射机制起源)
java文件被编译后,生成了 .class文件,jvm此时就要去解读 .class文件,被编译后的java文件 .class也被jvm解析为一个对象,这个对象就是 java.lang.Class 。这样当程序运行时,每个Java文件最终变成了Class 类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类称为一个动态的类。
class类中相关方法
常用获得类相关的方法
方法 | 用途 |
getClassLoader() | 获得类的加载器 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和对象的接口(包含私有) |
forName(String className) | 根据类名返回类的对象 |
newinstance() | 创建类的实例 |
getName() | 获得类的完整路径名字 |
public static void rel() throws ClassNotFoundException {创建对象
Class<?> c1 = Class.forName("reflectiondemo.stu");
try {
Object ob = c1.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
常用获得类中属性相关方法
方法 | 用途 |
getField(String name) | 获得某个公共的属性对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
Class<?> c9 = Class.forName("name");
try {
Object ob2 = c9.newInstance();
Field field = c9.getDeclaredField("name");
field.setAccessible(true);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
获得类中构造器相关的方法
方法 | 用途 |
getConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所以公有构造方法 |
getDeclaredConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
Class<?> c1 = forName("reflectiondemo.stu");
try {
Constructor<?> constructor = c1.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
stu st = (stu) constructor.newInstance("xiao ",18);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
获得类中方法相关方法
方法 | 用途 |
getClassLoader()
| 获得类的加载器 |
getDeclaredClasses()
| 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的) |
forName(String className)
| 根据类名返回类的对象 |
newInstance()
| 创建类的实例 |
getName()
| 获得类的完整路径名字 |
反射优点和缺点
优点:
1、对于任意一个类,都能够知道这个类所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。
2、增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
3、反射已经运用在了许多流行框架如:struts,Hibernate,spring .
缺点
1 、使用反射会有效率问题 我们可以看到 (实现一个反射过程需要实例化许多类。)
2、反射绕过了源代码技术,因而会带来维护问题。反射代码相比较直接代码更加复杂。