文章目录
假设已有下面的类:
- 示例类:Demo
package org.wangpai.reflectionuses.model;
/**
* @since 2022-9-11
*/
public class Demo {
private FieldA fieldA;
private FieldB fieldB;
/**
* 无参构造器
*
* @since 2022-9-11
*/
public Demo() {
System.out.println("无参构造器 Demo() 被调用");
System.out.println();
}
/**
* 有参构造器
*
* @since 2022-9-11
*/
public Demo(ParaA paraA, ParaB paraB) {
System.out.println("构造器 Demo(ParaA paraA, ParaB paraB) 被调用");
System.out.println(" > paraA:" + paraA);
System.out.println(" > paraB:" + paraB);
System.out.println();
this.fieldA = new FieldA(paraA.toString());
this.fieldB = new FieldB(paraB.toString());
}
/**
* 公有静态方法
*
* @since 2022-9-11
*/
public static void publicStaticFun(ParaA paraA, ParaB paraB) {
System.out.println("公有静态方法 publicStaticFun(ParaA paraA, ParaB paraB) 被调用");
System.out.println(" > paraA:" + paraA);
System.out.println(" > paraB:" + paraB);
System.out.println();
}
/**
* 私有有静态方法
*
* @since 2022-9-11
*/
private static void privateStaticFun(ParaA paraA, ParaB paraB) {
System.out.println("私有有静态方法 privateStaticFun(ParaA paraA, ParaB paraB) 被调用");
System.out.println(" > paraA:" + paraA);
System.out.println(" > paraB:" + paraB);
System.out.println();
}
/**
* 公有非静态方法
*
* @since 2022-9-11
*/
public void publicFun(ParaA paraA, ParaB paraB) {
System.out.println("公有方法 publicFun(ParaA paraA, ParaB paraB) 被调用");
System.out.println(" > paraA:" + paraA);
System.out.println(" > paraB:" + paraB);
System.out.println();
}
/**
* 私有非静态方法
*
* @since 2022-9-11
*/
private void privateFun(ParaA paraA, ParaB paraB) {
System.out.println("私有方法 privateFun(ParaA paraA, ParaB paraB) 被调用");
System.out.println(" > paraA:" + paraA);
System.out.println(" > paraB:" + paraB);
System.out.println();
}
/**
* 公有非静态可变参方法(无前面的固定参数)
*
* @since 2022-9-11
*/
public void publicVarParaFunWithNoFixedPara(ParaA... paraAS) {
System.out.println("公有可变参方法(无前面的固定参数) publicVarParaFunWithNoFixedPara(ParaA... paraAS) 被调用");
for (int order = 0; order < paraAS.length; ++order) {
System.out.println(String.format(" > 可变参参数,第 %d 参数是:", order + 1) + paraAS[order]);
}
System.out.println();
}
/**
* 公有非静态可变参方法(有前面的固定参数)
*
* @since 2022-9-11
*/
public void publicVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) {
System.out.println("公有可变参方法(有前面的固定参数) publicVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) 被调用");
System.out.println(" > 固定参数 paraA:" + paraA);
for (int order = 0; order < paraBs.length; ++order) {
System.out.println(String.format(" > 可变参参数,第 %d 参数是:", order + 1) + paraBs[order]);
}
System.out.println();
}
/**
* 私有非静态可变参方法(无前面的固定参数)
*
* @since 2022-9-11
*/
private void privateVarParaFunWithNoFixedPara(ParaA... ParaAs) {
System.out.println("私有可变参方法(无前面的固定参数) privateVarParaFunWithNoFixedPara(ParaA... ParaAs) 被调用");
for (int order = 0; order < ParaAs.length; ++order) {
System.out.println(String.format(" > 可变参参数,第 %d 参数:", order + 1) + ParaAs[order]);
}
System.out.println();
}
/**
* 私有非静态可变参方法(有前面的固定参数)
*
* @since 2022-9-11
*/
private void privateVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) {
System.out.println("私有可变参方法 privateVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) 被调用");
System.out.println(" > 固定参数 paraA:" + paraA);
for (int order = 0; order < paraBs.length; ++order) {
System.out.println(String.format(" > 可变参参数,第 %d 参数:", order + 1) + paraBs[order]);
}
System.out.println();
}
/**
* @since 2023-8-13
*/
public void showFields() {
System.out.println("公有方法 showFields() 被调用");
System.out.println(" > fieldA:" + this.fieldA);
System.out.println(" > fieldB:" + this.fieldB);
System.out.println();
}
}
- 字段类:FieldA
package org.wangpai.reflectionuses.model;
/**
* 参数类 FieldA
*
* @since 2023-8-13
*/
public class FieldA {
private String info;
/**
* @since 2023-8-13
*/
public FieldA() {
super();
}
/**
* @since 2023-8-13
*/
public FieldA(String str) {
super();
this.info = str;
}
/**
* @since 2023-8-13
*/
@Override
public String toString() {
return this.info;
}
}
- 字段类:FieldB
package org.wangpai.reflectionuses.model;
/**
* 参数类 FieldB
*
* @since 2023-8-13
*/
public class FieldB {
private String info;
/**
* @since 2023-8-13
*/
public FieldB() {
super();
}
/**
* @since 2023-8-13
*/
public FieldB(String str) {
super();
this.info = str;
}
/**
* @since 2023-8-13
*/
@Override
public String toString() {
return this.info;
}
}
- 参数类:ParaA
package org.wangpai.reflectionuses.model;
/**
* 参数类 ParaA
*
* @since 2022-9-11
*/
public class ParaA {
private String info;
public ParaA() {
super();
}
public ParaA(String str) {
super();
this.info = str;
}
@Override
public String toString() {
return this.info;
}
}
- 参数类:ParaB
package org.wangpai.reflectionuses.model;
/**
* 参数类 ParaB
*
* @since 2022-9-11
*/
public class ParaB {
private String info;
public ParaB() {
super();
}
public ParaB(String str) {
super();
this.info = str;
}
@Override
public String toString() {
return this.info;
}
}
反射访问字段
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
Demo demo = new Demo(paraA, paraB);
Field fA = demo.getClass().getDeclaredField("fieldA");
fA.setAccessible(true); // 设置允许反射读写私有字段
FieldA fieldA = (FieldA) fA.get(demo);
System.out.println("fieldA:" + fieldA);
构造器 Demo(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
fieldA:这是 ParaA
反射修改字段
ParaA paraA1 = new ParaA("这是 ParaA1");
ParaB paraB1 = new ParaB("这是 ParaB1");
Demo demo = new Demo(paraA1, paraB1);
FieldA fieldA2 = new FieldA("这是 FieldA2");
Field fA = demo.getClass().getDeclaredField("fieldA");
fA.setAccessible(true); // 设置允许反射读写私有字段
fA.set(demo, fieldA2);
demo.showFields();
构造器 Demo(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA1
> paraB:这是 ParaB1
公有方法 showFields() 被调用
> fieldA:这是 FieldA2
> fieldB:这是 ParaB1
反射创建对象
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
Demo demo = Demo.class
.getConstructor(ParaA.class, ParaB.class)
.newInstance(paraA, paraB);
构造器 Demo(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
反射调用方法
反射调用公有静态方法
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
Demo.class.getMethod("publicStaticFun", ParaA.class, ParaB.class)
.invoke(null, paraA, paraB);
公有静态方法 publicStaticFun(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
反射调用私有静态方法
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
var privateFun = Demo.class.getDeclaredMethod("privateStaticFun", ParaA.class, ParaB.class);
privateFun.setAccessible(true); // 如果此处的类本来就有权限调用用反射调用的方法,则此行代码可以省略
privateFun.invoke(null, paraA, paraB);
私有有静态方法 privateStaticFun(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
反射调用公有非静态方法
调用上述 Test 对象的可变参私有方法的办法是:
Demo demo = new Demo();
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
Demo.class.getMethod("publicFun", ParaA.class, ParaB.class)
.invoke(demo, paraA, paraB);
无参构造器 Demo() 被调用
公有方法 publicFun(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
反射调用私有非静态方法
Demo demo = new Demo();
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraB = new ParaB("这是 ParaB");
var privateFun = Demo.class.getDeclaredMethod("privateFun", ParaA.class, ParaB.class);
privateFun.setAccessible(true); // 如果此处的类本来就有权限调用用反射调用的方法,则此行代码可以省略
privateFun.invoke(demo, paraA, paraB);
无参构造器 Demo() 被调用
私有方法 privateFun(ParaA paraA, ParaB paraB) 被调用
> paraA:这是 ParaA
> paraB:这是 ParaB
反射调用公有非静态可变参方法(无前面的固定参数)
Demo demo = new Demo();
ParaA paraAOne = new ParaA("这是第一个 ParaA");
ParaA paraATwo = new ParaA("这是第二个 ParaA");
ParaA[] paraAs = new ParaA[]{paraAOne, paraATwo};
/**
* 虽然 paraAs 已经是数组,但此处还是要将可变参数组再封装到一个数组中。
* 不过,如果固定参数存在时,可以不用再外加数组,改为直接将各个元素列出。
* 此处因为固定参数不存在,所以需再套一层数组
*/
Demo.class.getMethod("publicVarParaFunWithNoFixedPara", ParaA[].class)
.invoke(demo, new Object[]{paraAs});
无参构造器 Demo() 被调用
公有可变参方法(无前面的固定参数) publicVarParaFunWithNoFixedPara(ParaA... paraAS) 被调用
> 可变参参数,第 1 参数是:这是第一个 ParaA
> 可变参参数,第 2 参数是:这是第二个 ParaA
反射调用私有非静态可变参方法(有前面的固定参数)
Demo demo = new Demo();
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraBOne = new ParaB("这是第一个 ParaB");
ParaB paraBTwo = new ParaB("这是第二个 ParaB");
ParaB[] paraBs = new ParaB[]{paraBOne, paraBTwo};
Demo.class.getDeclaredMethod("publicVarParaFunWithFixedPara", ParaA.class, ParaB[].class)
.invoke(demo, paraA, paraBs); // 因为固定参数有 1 个及以上,所以此处可以不用数组来包装
无参构造器 Demo() 被调用
公有可变参方法(有前面的固定参数) publicVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) 被调用
> 固定参数 paraA:这是 ParaA
> 可变参参数,第 1 参数是:这是第一个 ParaB
> 可变参参数,第 2 参数是:这是第二个 ParaB
反射调用私有非静态可变参方法(无前面的固定参数)
Demo demo = new Demo();
ParaA paraAOne = new ParaA("这是第一个 ParaA");
ParaA paraATwo = new ParaA("这是第二个 ParaA");
ParaA[] paraAs = new ParaA[]{paraAOne, paraATwo};
var privateFun = Demo.class.getDeclaredMethod(
"privateVarParaFunWithNoFixedPara", ParaA[].class);
privateFun.setAccessible(true);
/**
* 虽然 paraAs 已经是数组,但此处还是要将可变参数组再封装到一个数组中。
* 不过,如果固定参数存在时,可以不用再外加数组,改为直接将各个元素列出。
* 此处因为固定参数不存在,所以需再套一层数组
*/
privateFun.invoke(demo, new Object[]{paraAs});
无参构造器 Demo() 被调用
私有可变参方法(无前面的固定参数) privateVarParaFunWithNoFixedPara(ParaA... ParaAs) 被调用
> 可变参参数,第 1 参数:这是第一个 ParaA
> 可变参参数,第 2 参数:这是第二个 ParaA
反射调用私有非静态可变参方法(有前面的固定参数)
Demo demo = new Demo();
ParaA paraA = new ParaA("这是 ParaA");
ParaB paraBOne = new ParaB("这是第一个 ParaB");
ParaB paraBTwo = new ParaB("这是第二个 ParaB");
ParaB[] paraBs = new ParaB[]{paraBOne, paraBTwo};
var privateFun = Demo.class.getDeclaredMethod(
"privateVarParaFunWithFixedPara", ParaA.class, ParaB[].class);
privateFun.setAccessible(true);
// 因为固定参数有 1 个及以上,所以此处可以不用数组来包装
privateFun.invoke(demo, paraA, paraBs);
无参构造器 Demo() 被调用
私有可变参方法 privateVarParaFunWithFixedPara(ParaA paraA, ParaB... paraBs) 被调用
> 固定参数 paraA:这是 ParaA
> 可变参参数,第 1 参数:这是第一个 ParaB
> 可变参参数,第 2 参数:这是第二个 ParaB
反射创建数组
int arrayLength = 10;
// 注意:这样创建之后,得到的是一个空有长度无内容的空数组,因此,后续使用该数组,还需要依次初始化该数组的各个元素
Demo[] targetArray = (Demo[]) Array.newInstance(Demo[].class.getComponentType(), arrayLength);
反射调用的方法自身可以抛出异常的情形
如果反射调用的方法本身可以抛出异常,则当其抛出异常时,此异常会被反射“吞掉”,封装成 InvocationTargetException 异常重新抛出。可以使用该封装异常的方法 getTargetException 或 getCause 来获取被吞掉的异常。例如,
try {
/**
* 此处为某反射调用代码
*/
} catch (InvocationTargetException exception) {
Throwable realException = exception.getTargetException();
if (realException instanceof MyXXXException) {
throw (MyXXXException) realException;
} else {
// TODO:可以选择再抛出 InvocationTargetException 异常,也可以抛出自己想抛出的异常。或者做其它事情。
}
}
完整源代码
已上传至 GitHub 中,可免费下载:https://github.com/wangpaiblog/20210715_reflection-sample