基础知识
概念
- 反射是框架设计的灵魂。
- 反射机制就是将类的各个组成部分封装为其他对象。
优势
- 可以在程序运行过程中,操作这些对象。
- 可以解耦,提高程序的可扩展性。
Java代码的阶段
- Java代码在计算机中经历的三个阶段
- Source(源代码阶段)
- Java文件被Javac编译为class文件,class文件会将成员变量、成员方法和构造方法等编译成不同的模块。
- class文件通过 Classload类加载器 来进入和下一阶段。
- Class(类对象阶段)
- 通过 Classload类加载器,将class文件加载进内存,成员变量、成员方法和构造方法会被封装为Class类中的对象。
- Runtime(运行阶段)
- 当我们需要访问Java文件的成员时,我们就可以逆向访问,通过Class类的Classload类加载器来获取该成员的对象。
- Source(源代码阶段)
获取Class对象
- Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。
- 处于Source(源代码阶段),并未加载进内存。
- 用于配置文件,将类名定义在配置文件中。读取文件,从而加载类。
- 处于Source(源代码阶段),并未加载进内存。
- 类名.class:通过类名的属性class获取。
- 处于Class(类对象阶段),已经加载进内存。
- 多用于参数的传递。
- 处于Class(类对象阶段),已经加载进内存。
- 对象.getClass():Object类中定义的方法。
- Runtime(运行阶段),处于运行时。
- 用于获取对象的字节码文件对象。
- Runtime(运行阶段),处于运行时。
- Class类对象
- 同一个字节码文件( .class)在一次程序运行过程中,只会被加载一次。
- 不论通过哪一种方式获取的Class类对象都是同一个。
// Class类.静态方法forName("全类名")
Class class1 = Class.forName("com.test.Person");
// 类名.成员class
Class class2 = Person.class;
// 对象名.成员方法getClass()
Person person = new Person();
Class class3 = person.getClass();
获取成员变量
- Field[] getFields()
- 返回包含一个 Field对象数组,反射 所有可访问的 public字段类对象。
- Field getField(String name)
- 返回一个 Field对象,反射 指定的 public成员字段类对象。
- Field[] getDeclaredFields()
- 返回一个 Field对象,反射 所有可访问的 已声明字段类对象。(不考虑修饰符)
- Field getDeclaredField(String name)
- 返回一个 Field对象数组,反射 指定已声明字段类对象。(不考虑修饰符)
Person类中的成员变量
// public修饰符
public String publicName;
public int publicAge;
// private修饰符
private String privateName;
// protected修饰符
protected String protectedName;
// 无修饰符
String name;
获取Person类中的成员变量
Class pc = Person.class;
/* getField("") */
Field fie = pc.getField("publicName");
// public java.lang.String test.Person.publicName
/* getFields() */
Field[] fies = pc.getFields();
// public java.lang.String test.Person.publicName
// public int test.Person.publicAge
/* getDeclaredField("") */
Field fie = pc.getDeclaredField("privateName");
privateName.setAccessible(true);
// private java.lang.String test.Person.privateName
/* getDeclaradFields() */
Field[] fies = pc.getDeclaredFields();
for (Field fie : fies) {
fie.setAccessible(true);
}
// public java.lang.String test.Person.publicName
// private java.lang.String test.Person.privateName
// protected java.lang.String test.Person.protectedName
// java.lang.String test.Person.name
获取构造方法
- Constructor<?>[] getConstructors()
- 返回一个 Constructor对象,反射 指定的 public构造类对象。
- Constructor<T> getDeclaredConstructor(类<?>… parameterTypes)
- 返回一个 Constructor对象,反射 指定的 构造类对象。
- Constructor<T> getConstructor(类<?>… parameterTypes)
- 返回一个 Constructor对象数组,反射 所有的 public构造类对象。
- Constructor<?>[] getDeclaredConstructors()
- 返回一个 Constructor对象数组,反射 所有定的 构造类对象。
Person类中的构造方法
// 无参构造
public Person() {}
// public 带参构造(String)
public Person(String publicName) {}
// private 带参构造(String,String)
private Person(String publicName,String privateName) {}
获取Person类中的构造方法
/* getConstructor */
Constructor con = pc.getConstructor();
Object object = constructor.newInstance();
// {publicName='null', privateName='null'}
Constructor con = pc.getConstructor(String.class);
Object object = constructor2.newInstance("Cat");
// {publicName='Cat', privateName='null'}
/* getDeclaredConstructor */
Constructor con = pc.getDeclaredConstructor(String.class,String.class,);
declaredConstructor.setAccessible(true);
Object object = declaredConstructor1.newInstance("Pig","Pug");
// {publicName='Pig', privateName='Pug'}
/* getConstructors */
Constructor[] cons = pc.getConstructors();
// public test.Person()
// public test.Person(java.lang.String,)
/* getDeclaredConstructors */
Constructor[] cons = pc.getDeclaredConstructors();
// public test.Person()
// public test.Person(java.lang.String)
// private test.Person(java.lang.String,java.lang.String)
获取成员方法
- Method getMethod(String name, 类<?>… parameterTypes)
- 返回一个 Method对象,反射 指定的 public成员方法类对象。
- Method getDeclaredMethod(String name, 类<?>… parameterTypes)
- 返回一个 Method对象,反射 指定的 成员方法类对象。
- Method[] getMethods()
- 返回一个 Method对象数组,反射 所有的 public成员方法类对象。
- Method[] getDeclaredMethods()
- 返回一个 Method对象数组,反射 所有的 成员方法类对象。
Person类中的成员方法
// public修饰符
public void publicMethod111(){System.out.println("publicMethod()...");}
public void publicMethod222(String s){System.out.println("publicMethod("+ s +")...");}
// private修饰符
private void privateMethod(){System.out.println("privateMethod()...");}
// protected修饰符
protected void protectedMethod(){System.out.println("publicMethod()...");}
获取Person类中的成员方法
Class pc = Person.class;
Person p = new Person();
/* getMethod */
Method method = personClass.getMethod("publicMethod111");
// public void test.Person.publicMethod111()
method.invoke(p);
// publicMethod()...
Method method = personClass.getMethod("publicMethod222", String.class);
// public void test.Person.publicMethod222(java.lang.String)
method.invoke(p,"带参");
// publicMethod(带参)...
/* getDeclaredMethod */
Method method = pc.getDeclaredMethod("privateMethod");
//private void test.Person.privateMethod()
method.setAccessible(true);
method.invoke(p);
// privateMethod()...
/* getMethods */
Method[] methods = personClass.getMethods();
//public java.lang.String test.Person.toString()
//public java.lang.String test.Person.getName()
//public void test.Person.setName(java.lang.String)
//public void test.Person.publicMethod111()
//public void test.Person.publicMethod222(java.lang.String)
//public void test.Person.setPublicAge(int)
//public void test.Person.setProtectedName(java.lang.String)
//public int test.Person.getPublicAge()
// ................................
/* getDeclaredMethods */
Method[] methods = personClass.getDeclaredMethods();
// public java.lang.String test.Person.toString()
// public java.lang.String test.Person.getName()
// public void test.Person.setName(java.lang.String)
// public void test.Person.publicMethod111()
// protected void test.Person.protectedMethod()
// private void test.Person.privateMethod()
// public void test.Person.publicMethod222(java.lang.String)
// public void test.Person.setPublicAge(int)
// public void test.Person.setProtectedName(java.lang.String)
// ...............................
获取全类名
- String getName()
其他操作
操作Field
- 设置值
- void set(Object obj, Object value)
- 获取值
- get(Object obj)
- 暴力反射:忽略访问权限修饰符的安全检查
- setAccessible(true):暴力反射
Class pc = Person.class;
Person p = new Person();
/*public修饰符*/
Field fie = pc.getField("publicName");
// public java.lang.String test.Person.publicName
fie.set(p,"cat");
System.out.print( fie.get(p) );
// cat
/*private修饰符*/
Field fie = pc.getDeclaredField("privateName");
// private java.lang.String test.Person.privateName
pc.setAccessible(true);
pc.set(p,"dog");
System.out.print( fie.get(p) );
// dog
操作Constructor
- 创建对象
- T newInstance(Object… initargs)
- 如果使用空参数构造方法创建对象,操作可以简化
- Class对象的newInstance方法
/* Class */
Class pc = Person.class;
Object object = pc.newInstance();
// {publicName='null', privateName='null'}
/* Constructor */
Class pc = Person.class;
Constructor con = pc.getConstructor();
Object object = constructor.newInstance();
// {publicName='null', privateName='null'}
操作Method
- 执行方法
- Object invoke(Object obj, Object… args)
- 获取方法名
- String getName
Class pc = Person.class;
Person p = new Person();
Method method = personClass.getMethod("publicMethod111");
method.invoke(p);
// publicMethod()...