使用Java反射,我可以访问类型的私有静态嵌套类的私人领域?(Using Java reflecti

2019-10-28 16:23发布

我已经通过有关Java反射我能找到的,没有每个条目看上去似乎解决我处理的情况。 我有在它的静态的嵌套类的类A,B级A还具有作为其字段之一,B类型的数组,称为bArray。 我需要从类以及bArray的元素的私有成员外访问这一领域。 我已经能够得到使用getDeclaredClasses静态嵌套类和我通常会得到与getDeclaredFields和setAccessible私有字段bArray,但我似乎不能把它放在一起,能够从类的外部通过bArray进行迭代。

下面是我的工作的示例类结构。

public class A {
    private A.B[] bArray = new A.B[16];

    private static class B {
        private int theX;
        private int theY;

        B(int x, int y) {
            this.theX = x;
            this.theY = y;
        }
        // More methods of A.B not included   
    }
}

我最终需要获取bArray及其字段THEX,他们从A类之外

因为代码全部获得通过,通过混淆和名字除了在课程的字符串的那些所有的变化来看,我不能使用的类象的Class.forName的名字(“类名”)。 我可以利用场序(指数),但不是由于混淆的名称。 我已经成功地挑选出所有的,我需要这个以外的私人静态嵌套数组字段的字段,方法和诸如此类的东西。

这是我试过的方向。 这样做的第3行似乎做我想要什么,但4日说ABArray不能得到解决:

A myA = new A();
Class AB = stealNamedInnerClass(A.class);
Class ABArray = Array.newInstance(AB, 0).getClass();
ABArray myABArray = (ABArray)stealAndGetField(myA, ABArray);

这些都是实用功能,我引用:

public static Field stealField(Class typeOfClass, Class typeOfField)
{
    Field[] fields = typeOfClass.getDeclaredFields();
    for (Field f : fields) {
        if (f.getType().equals(typeOfField)) {
            try {
                f.setAccessible(true);
                return f;
            } catch (Exception e) {
                break; // Throw the Exception
            }
        }
    }
    throw new RuntimeException("Couldn't steal Field of type \"" + typeOfField + "\" from class \"" + typeOfClass + "\" !");
}

public static Object stealAndGetField(Object object, Class typeOfField)
{
    Class typeOfObject;

    if (object instanceof Class) { // User asked for static field:
        typeOfObject = (Class)object;
        object = null;
    } else {
        typeOfObject = object.getClass();
    }

    try {
        Field f = stealField(typeOfObject, typeOfField);
        return f.get(object);
    } catch (Exception e) {
        throw new RuntimeException("Couldn't get Field of type \"" + typeOfField + "\" from object \"" + object + "\" !");
    }
}

public static Class stealNamedInnerClass(Class clazz)
{
    Class innerClazz = null;
    Class[] innerClazzes = clazz.getDeclaredClasses();
    if (innerClazzes != null) {
        for (Class inner : innerClazzes) {
            if (!inner.isAnonymousClass())
                return inner;
        }
    }
    return null;
}

Answer 1:

Class实例不是Java编程语言的意义类型。 他们只是对象。 所以,你不能做

Class ABArray = Array.newInstance(AB, 0).getClass();
ABArray myABArray = (ABArray)stealAndGetField(myA, ABArray);

因为ABArray只是类型的对象Class ,而不是一种类型。 如果它是一个类型,它不会帮助无论如何,你要使用的类型不是从代码访问。 哪个是你的尝试是一回事,你试图访问一个什么private类使用普通Java语言结构是不可能的。 但是,你可以使用Object[]AB[]是的一个子类Object[]

A myA = new A();
Class AB = stealNamedInnerClass(A.class);
Class ABArray = Array.newInstance(AB, 0).getClass();
Object[] myABArray = (Object[])stealAndGetField(myA, ABArray);

需要注意的是处理元素Object是你(可以)通过反射访问它们只和反射方法都没有问题的Object作为输入反正。 当然,你将失去编译时类型安全,并在运行时只检测错误,但是这反映的不可避免的局限性。



Answer 2:

是的,你可以简单地在你的bArray迭代:

// First, get bArray
Class<A> aClass = A.class;
A instance = new A();
Class<?> bClass = aClass.getDeclaredClasses()[0];
Field field = aClass.getDeclaredField("bArray");
field.setAccessible(true);
Object[] bArray = (Object[]) field.get(instance);

// Then iterate and get field value
Field xField = bClass.getDeclaredField("theX");
xField.setAccessible(true);
Field yField = bClass.getDeclaredField("theY");
yField.setAccessible(true);
for (int i = 0; i < bArray.length; ++i) {
    Object bInstance = bArray[i];
    System.out.println("Item " + i + ": [x = " + xField.get(bInstance) + ", y = " + yField.get(bInstance) + "]");
}

当您正在测试它,请确保您的阵列完全初始化(即包含非空值)。



文章来源: Using Java reflection, can I access a private field of type private static nested class?