反射机制可以帮助我们在代码运行过程中,通过将字节码class文件添加到内存中,从而获取对象
开篇先放完整测试代码
package org.fssx;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class App {
public static void main( String[] args ) {
try {
Class cls = Class.forName("org.fssx.Person");
System.out.println("获取所有的公开构造函数");
Constructor [] constructors1 = cls.getConstructors();
for (Constructor c:constructors1){
System.out.println(c.toString());
}
System.out.println("获取所有的构造函数(包括非公开)");
Constructor [] constructors2 = cls.getDeclaredConstructors();
for (Constructor c:constructors2){
System.out.println(c.toString());
}
System.out.println("获取指定参数的构造函数");
Constructor constructor = cls.getConstructor(String.class,int.class);
System.out.println(cls.toString());
System.out.println("获取所有的公开方法");
Method [] methods1 = cls.getMethods();
for (Method m:methods1){
System.out.println(m.toString());
}
System.out.println("获取所有的方法(包括非公开)");
Method [] methods2 = cls.getDeclaredMethods();
for (Method m:methods2){
System.out.println(m.toString());
}
System.out.println("获取所有的公开属性");
Field [] fields1 = cls.getFields();
for (Field f:fields1){
System.out.println(f.toString());
}
System.out.println("获取所有的属性(包括非公开)");
Field [] fields2 = cls.getDeclaredFields();
for (Field f:fields2){
System.out.println(f.toString());
}
System.out.println("获取指定属性");
Field field = cls.getField("age");
System.out.println(field.toString());
System.out.println("获取指定属性(包括非public)");
Field field1 = cls.getDeclaredField("name");
System.out.println(field1.toString());
} catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | InstantiationException | IllegalAccessException | InvocationTargetException classNotFoundException) {
System.out.println("ERROR");
}
}
}
class Person{
static{
System.out.println("Static");
}
private String name;
public int age;
protected String sex;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private Person(String name){
this.name=name;
}
private void doSome(){
System.out.println("doSome");
}
public void doOther(String one,int two){
System.out.println("doOther");
}
}
获取类有以下几种方式
Class cls = Class.forName("com.fssx.Student"); // 此方法会调用类的static静态代码块
已经引用的情况下获取类
Class cls = Student.clss;
在实例化的情况下获取类
Student student = new Student();
Class cls = student.getClass();
获取类后有以下方法用于获取方法或者属性
// 获取构造函数
System.out.println("获取所有的公开构造函数");
Constructor [] constructors1 = cls.getConstructors();
System.out.println("获取所有的构造函数(包括非public)");
Constructor [] constructors2 = cls.getDeclaredConstructors();
System.out.println("获取指定参数的构造函数");
Constructor constructor = cls.getConstructor(String.class,int.class); // 获取指定参数的构造函数
// 获取方法
System.out.println("获取所有的公开方法");
Method [] methods1 = cls.getMethods();
System.out.println("获取所有的方法(包括非公开)");
Method [] methods2 = cls.getDeclaredMethods();
System.out.println("获取指定参数的方法");
Method method = cls.getMethod("doOther", String.class, int.class);
System.out.println("获取指定参数的方法(包括非public)");
Method method1 = cls.getDeclaredMethod("doSome");
//获取所有属性
System.out.println("获取所有的公开属性");
Field [] fields1 = cls.getFields();
System.out.println("获取所有的属性(包括非公开)");
Field [] fields2 = cls.getDeclaredFields();
System.out.println("获取指定属性");
Field field = cls.getField("age");
System.out.println("获取指定属性(包括非public)");
Field field1 = cls.getDeclaredField("name");
// 获取修饰符,通过getModifiers方法获取的是int类型,public是1,private是2,protected是4,static是8,final是16,通过Modifer.toString()可以将int转换为对应的修饰符
System.out.println("获取修饰符");
int resCode = method1.getModifiers();
System.out.println(resCode); // 1
String resModifier = Modifier.toString(resCode);
System.out.println(resModifier); // public
// 获取方法的参数列表
System.out.println("获取方法参数");
Class [] parameterTypes = method1.getParameterTypes();
for(Class clz:parameterTypes){
System.out.println(clz.toString());
}
// 实例化
System.out.println("实例化");
constructor.setAccessible(true); // 可以调用私有构造函数
Object app = constructor.newInstance("hello", 12); //通过构造函数实例化
method1.setAccessible(true); // 可以调用私有方法
method1.invoke(app,"one",12); // 调用方法,传入参数
field.setAccessible(true); // 可以调用私有属性
field.set(person, 22); // 设置属性值
看着方法好像很多,其实他是有一定规律的
1、在方法名末尾有s的是返回一个数组,没有s的是返回单个构造器。
2、在方法名中加Declared的是返回所有的构造方法,不加Declared的只返回public访问权限的构造器
3、有参数的都是在方法名中没有在结尾处加s的,返回的是指定参数类型的构造器