Java反射学习笔记,记录了Java反射的概念和相关类的学习笔记。
文章目录
Java反射简介
什么是Java反射?
Java反射是指Java的JVM会把Java文件中的各个部分(构造器、全局变量和方法)映射成对应对象。通过这些映射出来的对象,程序员可以进行对应功能的访问和执行。
- 用来编写一些通用性较高的代码或者框架的时候使用。
Java反射的机制
- Java反射必须先得到代表字节码文件的Class,Class类用于表示.class文件(字节码)。
- 需要使用Class类中的方法来解剖每个部分。
- Java文件每个部分对应使用的类,图:
Java反射使用步骤
- 获取Class类的对象。
- 通过Class类对象,执行Class类的方法返回单个构造器对象。
- 使用构造器类“Constructor”的方法创建实例。
- 获取和执行全局变量和方法的实现方式与上面类似,重复第2、3步骤,使用对应的Class类方法和对应类即可。
Java反射常用类
Class类
java.lang.Class类用于代表一个类的字节码文件(.class)。Class对象是由类的字节码文件(.class)被加载内存时所产生,代表正在运行的Java程序里的类或接口。使用Java反射时,需要在加载.class文件生成Class对象,然后使用Class类里的方法返回每个部分(构造器、全局变量、方法)的对象。
Class类的对象
使用Java反射第一步需要先获取Class对象。
Class对象获得的三种方法:
- 类名.class
- 对象.getClass()
- Class.forName(“包名.类名”)
例子:
//类名.class
Class c1 = Person.class;
//对象.getClass()
Person person = new Person();
Class c2 = person.getClass();
//Class.forName("包名.类名")
Class c3 = Class.forName("com.qqfh.reflect.Person");
Class类的方法
实例方法 | 说明 | 返回值 |
---|---|---|
getConstructors() | 获得类的所有构造方法 | Constructor[] |
getConstructor(Class<?>… parameterTypes) | 获得指定的构造器,参数填写对应"类型.Class" | Constructor |
getFields() | 返回此Class对象中的所有公有全局变量 | Field[] |
getDeclaredFields() | 返回此Class对象中的所有全局变量(包含私有) | Field[] |
getField(String name) | 返回Class对象中指定公有全局变量 | Field |
getDeclaredField(String name) | 返回Class对象中指定全局变量(包含私有) | Field |
getDeclaredMethods() | 获得此Class对象中的所有方法(包含私有) | Method[] |
getMethods() | 获得此Class对象中的公有方法 | Method[] |
getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回此Class对象中指定方法(包含私有) | Method |
getMethod(String name, Class<?>… parameterTypes) | 返回此Class对象中指定公有方法 | Method |
例子:
//创建Class对象,并获得有参数的构造器
Class c1 = Class.forName("com.qqfh.reflect.Person");
Constructor c =c1.getConstructor(String.class,String.class);
Constructor类
Constructor类对应类的构造方法以及对它的访问权限。Constructor对象代表类的单个构造方法。
实例方法 | 说明 | 返回值 |
---|---|---|
newInstance | 使用Constructor代表的构造器来创建新实例 | Object |
案例
/*
* 输出结果:
* 商品信息
* Goods [id=1, name=电风扇, price=59.9, desc=冬天大促销]
*/
private static void gouzaoqi() {
try {
//无参构造器
Class<?> c1 = Class.forName("com.qqfh.reflect.Goods");
Constructor<?> wucan = c1.getConstructor();
Goods g1 = (Goods)wucan.newInstance();
g1.display();
//有参数构造器
Class<?> c2 = Class.forName("com.qqfh.reflect.Goods");
Constructor<?> youcan = c2.getConstructor(int.class,String.class,double.class,String.class);
Goods g2 = (Goods)youcan.newInstance(1,"电风扇",59.9,"冬天大促销");
System.out.println(g2);
} catch (Exception e) {
e.printStackTrace();
}
}
Field类
Field类对应类或接口的全局变量(字段、成员变量)信息,并提供动态访问权限。
实例方法 | 说明 | 返回值 |
---|---|---|
setAccessible(boolean flag) | 设置Filed变量是否可以访问私有属性,true表示可以,默认值false | void |
get(Object obj) | 获取指定对象中此Field所对应变量的值 | Object |
set(Object obj, Object value) | 设置指定对象中此Field所对应变量的值 | void |
getDeclaredField | 获取私有属性 | Field |
案例
/*
* 通过Field获得私有属性
* 输出结果:
* 三国演义
* Goods [id=0, name=三国演义, price=0.0, desc=null]
*/
public static void FieldTest1() {
try {
Class<?> c1 = Class.forName("com.qqfh.reflect.Goods");
Field f1 = c1.getDeclaredField("name");
f1.setAccessible(true);
Goods goods = new Goods();
f1.set(goods, "三国演义");
Object result = f1.get(goods);
System.out.println(result);
System.out.println(goods);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 通过Field获得公有属性
* 输出结果:
* 59.9
* Goods [id=0, name=null, price=59.9, desc=null]
*/
public static void FieldTest2() {
try {
Class<?> c1 = Class.forName("com.qqfh.reflect.Goods");
Field f1 = c1.getField("price");
Goods goods = new Goods();
f1.set(goods,59.9);
Object result = f1.get(goods);
System.out.println(result);
System.out.println(goods);
} catch (Exception e) {
e.printStackTrace();
}
}
Method类
Method对应类或接口上方法的信息。
实例方法 | 说明 | 返回值 |
---|---|---|
setAccessible(boolean flag) | 设置Filed变量是否可以访问私有属性,true表示可以,默认值false | void |
invoke(Object obj, Object… args) | 执行obj对象中此Method对应的方法。后一个Object是方法参数 | Object |
案例
// 1)通过Method调用display()方法
public static void mdisplay() {
try {
Class c1 =Class.forName("com.qqfh.reflect.Address");
Method m1 = c1.getMethod("display");
Address addr = new Address();
m1.invoke(addr);
} catch (Exception e) {
e.printStackTrace();
}
}
// 2)通过Method调用info()方法
public static void minfo() {
try {
Class c1 =Class.forName("com.qqfh.reflect.Address");
Method m1 = c1.getDeclaredMethod("info",null);
m1.setAccessible(true);
Address addr = new Address();
m1.invoke(addr);
} catch (Exception e) {
e.printStackTrace();
}
}
// 3)通过Method调用equalsAddress(String name)方法
public static void mequalsAddress() {
try {
Class c1 =Class.forName("com.qqfh.reflect.Address");
Method m1 = c1.getDeclaredMethod("equalsAddress",String.class);
m1.setAccessible(true);
Address addr = new Address(1,"张三","北京","13012341234");
m1.invoke(addr,"李四");
m1.invoke(addr,"张三");
} catch (Exception e) {
e.printStackTrace();
}
}