如何使用反射获取匿名 class 字段
how to get anonymous class fields by using reflection
这是我的示例 classes,我想通过反射获取 y 和 z 字段
在这一行中 (Field[] Fields = forName.getDeclaredFields();) 得到空数组。如果 y 和 z 不是 class 结构的一部分,那么它们属于哪个部分
package test;
import java.lang.reflect.Field;
public class Reflection {
static ClassLoader classLoader = null;
public static void main(String[] args) {
classLoader = Reflection.class.getClassLoader();
Reflection r = new Reflection();
r.getAnnClas();
}
private void getAnnClas() {
Class<?> forName = null;
try {
forName = classLoader.loadClass("test.Wrirter");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] declaredFields = forName.getDeclaredFields();
for (Field field : declaredFields) {
//here i canot find annoumouse calss filed Z
System.out.println(field.getName());
}
}
}
package test;
import java.io.File;
import java.io.FileReader;
public class Wrirter {
public Cb c= new Cb(10, 20) {
public int z = 10;
public int y=120;
@Override
public void doSom() {
super.doSom();
int cbf = getIntC() + getIntB();
}
};
public Wrirter() {
}
}
class Cb {
public int c;
public int b;
public Cb(int c, int b) {
this.c = c;
this.b = b;
}
public void doSom() {
}
public int getIntC() {
return c;
}
public int getIntB() {
return b;
}
public int setIntC() {
return c;
}
public int setIntB() {
return b;
}
}
这不可能。 y
和 z
不是 class 结构的一部分。
您需要对匿名 class 进行操作,而不是对封闭的外部进行操作。
在下面找到一个精简的示例来演示原理
// the outer class type
Class<?> forName = Wrirter.class;
// instance to investigate
Wrirter outerClass = new Wrirter();
// call the method which create an object of the anonymous class
outerClass.ann();
// get the field which holds a reference to the anonymous class
Field fieldAnonymousClass = forName.getDeclaredField("c");
// get the reference to the anonymous class
Object instanceAnonymousClass = fieldAnonymousClass.get(outerClass);
// get the class type of the anonymous class
Class anonymousClassType = instanceAnonymousClass.getClass();
System.out.println("anonymous class name: " + anonymousClassType.getName());
// get the declared fields of the anonymous class
Field[] declaredFields = anonymousClassType.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == int.class) {
// print the field name and its value
System.out.printf("name: %s value: %s%n",
field.getName(),
field.getInt(instanceAnonymousClass)
);
}
}
输出
anonymous class name: Wrirter
name: y value: 10
name: z value: 20
编辑 获取没有对象引用的匿名 class 的字段名称。
// assuming you have already the anonymous class name
Class<?> anonymousClassType = Class.forName("Wrirter");
// get the declared fields of the anonymous class
Field[] declaredFields = anonymousClassType.getDeclaredFields();
for (Field field : declaredFields) {
System.out.printf("type: %s name: %s%n",
field.getType(),
field.getName()
);
}
输出
type: int name: y
type: int name: z
编辑 2 在下面找到一段如何使用 Javassist.
获取 class 的常量池中引用的 class 名称
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Wrirter");
ConstPool classConstantPool = cc.getClassFile().getConstPool();
for (String className : (Set<String>) classConstantPool.getClassNames()) {
System.out.println("className = " + className);
}
输出
className = java/lang/Object
className = Wrirter
className = Wrirter
这是我的示例 classes,我想通过反射获取 y 和 z 字段 在这一行中 (Field[] Fields = forName.getDeclaredFields();) 得到空数组。如果 y 和 z 不是 class 结构的一部分,那么它们属于哪个部分
package test;
import java.lang.reflect.Field;
public class Reflection {
static ClassLoader classLoader = null;
public static void main(String[] args) {
classLoader = Reflection.class.getClassLoader();
Reflection r = new Reflection();
r.getAnnClas();
}
private void getAnnClas() {
Class<?> forName = null;
try {
forName = classLoader.loadClass("test.Wrirter");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] declaredFields = forName.getDeclaredFields();
for (Field field : declaredFields) {
//here i canot find annoumouse calss filed Z
System.out.println(field.getName());
}
}
}
package test;
import java.io.File;
import java.io.FileReader;
public class Wrirter {
public Cb c= new Cb(10, 20) {
public int z = 10;
public int y=120;
@Override
public void doSom() {
super.doSom();
int cbf = getIntC() + getIntB();
}
};
public Wrirter() {
}
}
class Cb {
public int c;
public int b;
public Cb(int c, int b) {
this.c = c;
this.b = b;
}
public void doSom() {
}
public int getIntC() {
return c;
}
public int getIntB() {
return b;
}
public int setIntC() {
return c;
}
public int setIntB() {
return b;
}
}
这不可能。 y
和 z
不是 class 结构的一部分。
您需要对匿名 class 进行操作,而不是对封闭的外部进行操作。
在下面找到一个精简的示例来演示原理
// the outer class type
Class<?> forName = Wrirter.class;
// instance to investigate
Wrirter outerClass = new Wrirter();
// call the method which create an object of the anonymous class
outerClass.ann();
// get the field which holds a reference to the anonymous class
Field fieldAnonymousClass = forName.getDeclaredField("c");
// get the reference to the anonymous class
Object instanceAnonymousClass = fieldAnonymousClass.get(outerClass);
// get the class type of the anonymous class
Class anonymousClassType = instanceAnonymousClass.getClass();
System.out.println("anonymous class name: " + anonymousClassType.getName());
// get the declared fields of the anonymous class
Field[] declaredFields = anonymousClassType.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getType() == int.class) {
// print the field name and its value
System.out.printf("name: %s value: %s%n",
field.getName(),
field.getInt(instanceAnonymousClass)
);
}
}
输出
anonymous class name: Wrirter
name: y value: 10
name: z value: 20
编辑 获取没有对象引用的匿名 class 的字段名称。
// assuming you have already the anonymous class name
Class<?> anonymousClassType = Class.forName("Wrirter");
// get the declared fields of the anonymous class
Field[] declaredFields = anonymousClassType.getDeclaredFields();
for (Field field : declaredFields) {
System.out.printf("type: %s name: %s%n",
field.getType(),
field.getName()
);
}
输出
type: int name: y
type: int name: z
编辑 2 在下面找到一段如何使用 Javassist.
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Wrirter");
ConstPool classConstantPool = cc.getClassFile().getConstPool();
for (String className : (Set<String>) classConstantPool.getClassNames()) {
System.out.println("className = " + className);
}
输出
className = java/lang/Object
className = Wrirter
className = Wrirter