一、什么是反射
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。
本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
通过反射,可以在运行时动态地创建对象并调用其属性。
二、反射的原理及优缺点
三、反射的应用与基本功能
1、反编译:.class -> .java
2、通用框架。如:Spring中通过XML文件配置Bean。
基本功能
在运行时判断任意一个对象所属的类; 在运行时判断任意一个类的对象 在运行时判断任意一个类所具有的成员变量及方法 在运行时调用任意一个对象的方法
重点:在运行时而不是编译时。
四、反射机制常用的类
java.lang.Class
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.Modifier
五、反射的基本使用方法
package com.cimon.reflectdemo;
public class Student {
@Getter
private int age;
Student (int age){
this.age = age;
}
Student(){
this.age = 12;
}
private Student(String age){
this.age = Integer.valueOf(age);
}
public int doHomework(){
return 1;
}
public String toString(){
return String.valueOf(this.age);
}
}
5.1、获取Class
1、Object -> getClass 2、任何数据类型(包括基本的数据类型)都有一个“静态”的class属性。 3、通过class类的静态方法:forName(String className)。常用。
运行期间,一个类只有一个Class对象产生。
public class StudentTest {
public static void main(String args[]) throws ClassNotFoundException{
//方式一
Student student = new Student(12);
Class studentClass1 = student.getClass();
System.out.println(studentClass1.getName());
//方式二
Class studentClass2 = Student.class;
System.out.println(studentClass2.getName());
//方式三
Class studentClass3 = Class.forName("com.cimon.reflectdemo.Student");
System.out.println(studentClass3.getName());
System.out.println(studentClass2==studentClass1);
System.out.println(studentClass3==studentClass1);
}
}
运行结果:
com.cimon.reflectdemo.Student
com.cimon.reflectdemo.Student
com.cimon.reflectdemo.Student
true
true
5.2、类的实例判断
public native boolean isInstance(Object obj);
5.3、创建实例:反射
方法一:使用Class对象的newInstance()方法
Class<?> c = String.Class;
Object str = c.newInstance();
方法二:通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance方法来创建对象。这种方法可以指定参数
Class<?> c = String.class;
Constructor constructor=c.getConstructor(String.class);
Object obj = constructor.newInstance(“hello reflection”);
5.4、使用反射获取构造方法
1、批量获取方法
public Constructor[] getConstructors(); //所有公有方法
public Constructor[] getDeclaredConstructors(); // 获取所有构造方法(私有、保护...)
2、单个获取的方法
public Constructor getConstructors(Class.. parameterTypes) 获取单个的公有构造方法
public Constructor getDeclaredConstructors(Class.. parameterTypes) 获取单个的构造方法
3、调用构造方法
Contructor.newInstance(Obejct... initargs) //指定初始化参数
package com.cimon.reflectdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ContructorTest {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class studentClass = Class.forName("com.cimon.reflectdemo.Student");
Constructor[] constructors = studentClass.getDeclaredConstructors();
for(Constructor c : constructors){
System.out.println(c);
}
System.out.println(" ...... 调用构造方法..... ");
Constructor c1 = studentClass.getDeclaredConstructor(String.class);
System.out.println(c1);
c1.setAccessible(true);// 强制访问
Object obj = c1.newInstance("123");
}
}
运行结果:
private com.cimon.reflectdemo.Student(java.lang.String)
com.cimon.reflectdemo.Student()
com.cimon.reflectdemo.Student(int)
...... 调用构造方法.....
private com.cimon.reflectdemo.Student(java.lang.String)
5.5 获取成员变量
package com.cimon.reflectdemo;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class FiledTest {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class studentClass = Class.forName("com.cimon.reflectdemo.Student");
Field[] fields = studentClass.getDeclaredFields();
for(Field f : fields){
System.out.println(f);
}
System.out.println("...... 测试设置属性 .......");
Object student = studentClass.getDeclaredConstructor(java.lang.Integer.TYPE).newInstance(12);
System.out.println("before set ... " + student);
Field f = studentClass.getDeclaredField("age");
f.setAccessible(true);
f.set(student,123);
System.out.println("after set ... " + student);
}
}
运行结果:
private int com.cimon.reflectdemo.Student.age
...... 测试设置属性 .......
before set ... 12
after set ... 123
5.6 获取方法
使用invoke调用获取到的方法。
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,InvocationTargetException
package com.cimon.reflectdemo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodTest {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class studentClass = Class.forName("com.cimon.reflectdemo.Student");
Method[] methods = studentClass.getDeclaredMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println(" ..... 测试方法 ....");
Object obj = studentClass.getDeclaredConstructor(int.class).newInstance(123);
Method m1 = studentClass.getDeclaredMethod("getAge");
Object result = m1.invoke(obj);
System.out.println(result);
}
}
运行结果:
public java.lang.String com.cimon.reflectdemo.Student.toString()
public int com.cimon.reflectdemo.Student.doHomework()
public int com.cimon.reflectdemo.Student.getAge()
..... 测试方法 ....
123