Java反射学习笔记文章目录
- 1 反射简介
- 1.1 什么是反射
- 1.2 反射的好处
- 1.3 Java代码在计算机中经历的三个阶段
- 1.4 获取Class对象的方式
- 2 class对象功能
- 2.1 获取成员变量
- 2.2 获取构造方法
- 2.3 获取成员方法
- 2.4 获取类名
- 3 成员变量Field功能
- 3.1 获取值
- 3.2 设置值
- 3.3 暴力反射
- 4 构造方法功能
- 4.1 创建对象
- 4.2 暴力反射
- 5 成员方法功能
- 5.1 执行方法
- 5.2 获取方法名
- 5.3 暴力反射
- 6 写一个框架
- 6.1 需求
- 6.2 步骤
- 6.3 代码
反射:框架设计的灵魂
将类的各个组成部分封装为其他对象,这就是反射。
1.2 反射的好处 1.可以在程序运行过程中,操作这些对象
2.可以解耦,提高程序的可扩展性
1.3 Java代码在计算机中经历的三个阶段 1.4 获取Class对象的方式 1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象 ----多用于配置文件,读取文件,加载类 如struts2配置文件
2.类名.Class : 通过类名的属性class获取 ----多用于参数的传递
3.对象.Class : getClass()方法在Object类中定义着。 --多用于对象的获取字节码
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
2 class对象功能Person.java
package com.tangguanlin.reflect;
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
", a='" + a + ''' +
", b='" + b + ''' +
", c='" + c + ''' +
", d='" + d + ''' +
'}';
}
}
2.1 获取成员变量
Field[] getFields() : 获取所有public修饰的成员变量 Field getField(String name) : 获取指定名称的public修饰的成员变量 Field[] getDeclaredFields() : 获取所有的成员变量(不考虑修饰符) Field getDeclaredField(String name): 获取指定名称的成员变量(不考虑修饰符)
代码:
ReflectTest2.java
package com.tangguanlin.reflect;
import java.lang.reflect.Field;
public class ReflectTest2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//0.获取Person的Class对象
Class personClass = Person.class;
//1 获取成员变量
Field[] fields = personClass.getFields();
for(Field field:fields){
System.out.println(field);
}
Field[] declaredFields = personClass.getDeclaredFields();
for(Field field:declaredFields){
System.out.println("getDeclaredFields:"+field);
}
Field a = personClass.getField("a");
//获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置成员变量a的值
a.set(p,"张三");
System.out.println(p);
Field nameField = personClass.getDeclaredField("name");
System.out.println("getDeclaredField:"+nameField);
//忽略访问权限修饰符的安全检查
nameField.setAccessible(true); //暴力反射
nameField.get(p);
nameField.set(p,"lisi");
System.out.println(p);
}
}
运行结果:
public java.lang.String com.tangguanlin.reflect.Person.a
getDeclaredFields:private java.lang.String com.tangguanlin.reflect.Person.name
getDeclaredFields:private int com.tangguanlin.reflect.Person.age
getDeclaredFields:public java.lang.String com.tangguanlin.reflect.Person.a
getDeclaredFields:protected java.lang.String com.tangguanlin.reflect.Person.b
getDeclaredFields:java.lang.String com.tangguanlin.reflect.Person.c
getDeclaredFields:private java.lang.String com.tangguanlin.reflect.Person.d
null
Person{name='null', age=0, a='张三', b='null', c='null', d='null'}
getDeclaredField:private java.lang.String com.tangguanlin.reflect.Person.name
Person{name='lisi', age=0, a='张三', b='null', c='null', d='null'}
2.2 获取构造方法
Constructor[] getConstructors() : 获取所有public修饰的构造方法 Constructor getConstructor(String.class, int.class); 获取指定参数类型的public修饰的构造方法 Constructor[] getDeclaredConstructors(): 获取所有的构造方法(不考虑修饰符) Constructor getDeclaredConstructor(String.class, int.class) 获取指定参数类型的构造方法(不考虑修饰符)
代码:
ReflectTest3.java
package com.tangguanlin.reflect;
import org.apache.poi.util.SystemOutLogger;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectTest3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//0.获取Person的Class对象
Class personClass = Person.class;
//1.获取构造方法
Constructor[] constructors = personClass.getConstructors();
for(Constructor constructor:constructors){
System.out.println("--getConstructors()--"+constructor);
}
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
Constructor[] declaredConstructors = personClass.getDeclaredConstructors();
for(Constructor declaredConstructor:constructors){
System.out.println("--getDeclaredConstructors()--"+declaredConstructor);
}
Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
System.out.println("--getDeclaredConstructor()--"+declaredConstructor);
//用构造方法创建对象
Object p5 = constructor.newInstance("wangwu", 23);
System.out.println(p5);
Constructor constructor1 = personClass.getDeclaredConstructor();
Object p6 = constructor1.newInstance();
System.out.println(p6);
//等价于
Object p7 = personClass.newInstance();
System.out.println(p7);
//暴力反射
constructor1.setAccessible(true);
}
}
运行结果:
--getConstructors()--public com.tangguanlin.reflect.Person(java.lang.String,int)
--getConstructors()--public com.tangguanlin.reflect.Person()
public com.tangguanlin.reflect.Person(java.lang.String,int)
--getDeclaredConstructors()--public com.tangguanlin.reflect.Person(java.lang.String,int)
--getDeclaredConstructors()--public com.tangguanlin.reflect.Person()
--getDeclaredConstructor()--public com.tangguanlin.reflect.Person(java.lang.String,int)
Person{name='wangwu', age=23, a='null', b='null', c='null', d='null'}
Person{name='null', age=0, a='null', b='null', c='null', d='null'}
Person{name='null', age=0, a='null', b='null', c='null', d='null'}
2.3 获取成员方法
Method[] getMethods() : 获取所有public修饰的成员方法 Method getMethod(方法名称, int.class): 获取指定方法名称的public修饰的成员方法 Method[] getDeclaredMethods() : 获取所有的成员方法(不考虑修饰符) Method getDeclaredMethods(方法名称, int.class): 获取指定方法名的成员方法(不考虑修饰符)
代码:
ReflectTest4.java
package com.tangguanlin.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest4 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//0.获取Person的Class对象
Class personClass = Person.class;
//1.获取所有public成员方法
Method[] methods = personClass.getMethods();
for(Method method:methods){
System.out.println("--getMethods()--"+method);
}
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);
Person p = new Person();
//执行成员方法
eatMethod.invoke(p, 5);
//获取所有的成员方法(不考虑修饰符)
Method[] declaredMethods = personClass.getDeclaredMethods();
for(Method declaredMethod:declaredMethods){
System.out.println("--getDeclaredMethods()--"+declaredMethod);
}
}
}
运行结果:
--getMethods()--public java.lang.String com.tangguanlin.reflect.Person.toString() --getMethods()--public java.lang.String com.tangguanlin.reflect.Person.getName() --getMethods()--public void com.tangguanlin.reflect.Person.setName(java.lang.String) --getMethods()--public void com.tangguanlin.reflect.Person.eat(int) --getMethods()--public int com.tangguanlin.reflect.Person.getAge() --getMethods()--public void com.tangguanlin.reflect.Person.setAge(int) --getMethods()--public final void java.lang.Object.wait() throws java.lang.InterruptedException --getMethods()--public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException --getMethods()--public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException --getMethods()--public boolean java.lang.Object.equals(java.lang.Object) --getMethods()--public native int java.lang.Object.hashCode() --getMethods()--public final native java.lang.Class java.lang.Object.getClass() --getMethods()--public final native void java.lang.Object.notify() --getMethods()--public final native void java.lang.Object.notifyAll() eat0... eat1... eat2... eat3... eat4... --getDeclaredMethods()--public java.lang.String com.tangguanlin.reflect.Person.toString() --getDeclaredMethods()--public java.lang.String com.tangguanlin.reflect.Person.getName() --getDeclaredMethods()--public void com.tangguanlin.reflect.Person.setName(java.lang.String) --getDeclaredMethods()--public void com.tangguanlin.reflect.Person.eat(int) --getDeclaredMethods()--public int com.tangguanlin.reflect.Person.getAge() --getDeclaredMethods()--public void com.tangguanlin.reflect.Person.setAge(int) --getDeclaredMethods()--private void com.tangguanlin.reflect.Person.sing()2.4 获取类名
语法:personClass.getName()
//获取类名
String className = personClass.getName();
System.out.println("获取类名:"+className);
运行结果:
获取类名:com.tangguanlin.reflect.Person3 成员变量Field功能 3.1 获取值
String value = a.get(p);
3.2 设置值a.set(p,"张三");3.3 暴力反射
忽略访问权限修饰符的安全检查
#忽略访问权限修饰符的安全检查 nameField.setAccessible(true);4 构造方法功能 4.1 创建对象
构造方法Constructor功能:创建对象
Object p5 = constructor.newInstance("wangwu", 23);
Constructor constructor = personClass.getDeclaredConstructor(); //空参构造函数
Object p6 = constructor.newInstance();
//等价于
Object p7 = personClass.newInstance(); //一般使用这种方式
4.2 暴力反射
构造方法 也有暴力反射
Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class); //暴力反射 declaredConstructor.setAccessible(true);5 成员方法功能 5.1 执行方法
语法:eatMethod.invoke(对象, 方法参数列表);
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);
Person p = new Person();
//执行成员方法
eatMethod.invoke(p, 5);
5.2 获取方法名
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);
//获取成员方法名称
System.out.println("eat方法名"+eatMethod.getName());
运行结果:
eat方法名eat5.3 暴力反射
//获取指定名称的成员方法
Method eatMethod = personClass.getMethod("eat", int.class);
//成员方法暴力反射
eatMethod.setAccessible(true);
6 写一个框架
案例:体现反射的魅力所在
6.1 需求 需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
实现:
1.配置文件
2.反射
6.2 步骤 步骤:
1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
2.在程序中加载读取配置文件
3.使用反射技术来加载类文件进内存
4.创建对象
5.执行方法
6.3 代码Person.java
package com.tangguanlin.reflect;
public class Person {
public void sing(){
System.out.println("sing...");
}
}
Student.java
package com.tangguanlin.reflect;
public class Student {
public void sleep(){
System.out.println("sleep...");
}
}
pro.properties配置文件
className=com.tangguanlin.reflect.Person methodName=sing
ReflectTest5.java
package com.tangguanlin.reflect;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectTest5 {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//可以执行创建任意类的对象,可以执行任意方法
//1.加载配置文件
//1.1创建Properties对象
Properties pro = new Properties(); //专门读取properties文件的工具
//1.2加载配置文件,转换为一个集合
//1.2.1 获取class目录下的配置文件
//获取类加载器
ClassLoader classLoader = ReflectTest5.class.getClassLoader();
//用类加载器加载配置文件
InputStream is = classLoader.getResourceAsStream("pro.properties");
//FileInputStream fis = new FileInputStream("pro.properties"); //等价
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class c1= Class.forName(className);
//4.创建对象
Object object = c1.newInstance();
// 5.获取方法对象
Method method = c1.getMethod(methodName);
//6.执行方法
method.invoke(object);
}
}
运行结果:
sing...
修改配置文件pro.properties
className=com.tangguanlin.reflect.Student methodName=sleep
运行结果:
sleep...



