反射机制(reflection)
Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任何一个对象,都能调用它的任意方法和属性,既然可以拿到,那就可以修改部分类型信息;这种动态获取信息以及动态调用方法的功能称为Java语言的反射机制
应用
<1>. 反射最重要的作用是开发各种通用的框架
<2>. 在日常的第三方应用开发的过程中,经常遇到某个类的某个成员变量、方法或是私有的或是只对系统应用开发的,这时候就可以用Java反射机制获取私有成员或方法
<3>. 反射基本信息
Java程序中许多对象运行时会有两种类型:
运行时类型和编译时类型
程序运行本质是在运行时发现对象的类的真实信息,通过反射机制可以判断出该对象和类属于那些类
| 类名 | 用途 |
|---|---|
| Class类 | 代表类的实体,在运行Java应用程序中表示类的接口 |
| Field类 | 代表类的成员变量/类的属性 |
| Method类 | 代表类的方法 |
| Constructor类 | 代表类的构造方法 |
1. 常用获得类相关的方法
| 方法 | 用途 |
|---|---|
| getClassLoader() | 获得类的加载器 |
| getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有) |
| forName(String className) | 根据类名返回类的对象 |
| newInstance() | 创建类的实例 |
| getName() | 获得类的完整路径名字 |
| 方法 | 用途 |
|---|---|
| getField(String name) | 获得某个公有的属性对象 |
| getFields() | 获得所有公有的属性对象 |
| getDeclaredField(String name) | 获得某个属性对象 |
| getDeclaredFields() | 获得所有属性对象 |
| 方法 | 用途 |
|---|---|
| getConstructor(Class…>parameter Types) | 获得该类中与参数类型匹配的公有构造方法 |
| getConstructors() | 获得该类的所有公有构造方法 |
| getDeclaredConstructor(Class…> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
| getDeclaredConstructors() | 获得该类所有构造方法 |
| 方法 | 用途 |
|---|---|
| getMethod(String name, Class…> parameterTypes) | 获得该类某个公有的方法 |
| getMethods() | 获得该类所有公有的方法 |
| getDeclaredMethod(String name, Class…> parameterTypes) | 获得该类某个方法 |
| getDeclaredMethods() | 获得该类所有方法 |
(1)获得Class对象的三种方式
public static void main(String[] args) throws ClassNotFoundException {
//1.通过Class对象的forName()静态方法获取(用的最多,注意抛异常)
Class<?> c1 = Class.forName("reflectdemo.Student");
}
//2.通过getClass获取class对象
Student student = new Student();
Class<?> c2 = student.getClass();
//3.直接通过 类型.class获取(更安全可靠,程序性能更高)
Class<?> c3 = Student.class;
(2)反射的使用——所有和反射相关的包都在 import.java.lang.reefelect包下
//1 通过反射创建对象
public static void reflectNewInstance() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
System.out.println(student);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//2 反射私有的构造方法,屏蔽内容为获得公有的构造方法
public static void reflectPrivateConstructor() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
//注意传入对应的参数
Constructor<?> constructor =
c1.getDeclaredConstructor(String.class, int.class);
//你确定要在类外访问私有方法吗.设置为true后可修改访问权限
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("xiangyu",22);
System.out.println(student);
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//3.反射私有属性
public static void reflectPrivateField() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
//可以修改该属性的值
Field field = c1.getDeclaredField("name");
//访问私有的,提前询问一下是否确定访问
field.setAccessible(true);
field.set(student,"liubang");
System.out.println(student);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
//4. 反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
Method method = c1.getDeclaredMethod("function", String.class);
method.setAccessible(true);
method.invoke(student,"通过反射给你传参");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}//3.反射私有属性
public static void reflectPrivateField() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
//可以修改该属性的值
Field field = c1.getDeclaredField("name");
//访问私有的,提前询问一下是否确定访问
field.setAccessible(true);
field.set(student,"liubang");
System.out.println(student);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
//4. 反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
Method method = c1.getDeclaredMethod("function", String.class);
method.setAccessible(true);
method.invoke(student,"通过反射给你传参");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
优点:
- 任意一个类,都可以知道这个类的所有属性和方法;任意一个对象,都可以调用它的任意一个方法
- 增加程序的灵活性和拓展性,降低耦合,提高自适应能力
- 反射应用在好多框架上
缺点:
- 反射因调用好多方法,可能存在效率降低的问题
- 反射技术绕过了源代码的技术,会有维护的问题,并且反射代码比相应直接代码更加复杂