获取非可实例化类的字段值 - 反射

3
如何迭代并获取非可实例化类的所有字段的值:
import java.lang.reflect.Field;

public class NonInstantiableClass {
    private Integer a1 = 1;
    private String a2 = "a";

    private NonInstantiableClass () {
         throw new AssertionError();
    }

    public static void printVariables () throws IllegalAccessException {

        for (Field field : NonInstantiableClass.class.getDeclaredFields()) {
            field.setAccessible(true);
            System.out.println(field.getName()
                    + " - " + field.getType()
                    + " - " + field.get(NonInstantiableClass.class));
        }
    }


    public static void main(String args[]) throws IllegalAccessException {
        NonInstantiableClass.printVariables();
    }
}

考虑到这段代码会出现以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field NonInstanciableClass.a1 to java.lang.Class
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.base/java.lang.reflect.Field.get(Field.java:418)
    at NonInstanciableClass.printVariables(NonInstanciableClass.java:17)
    at NonInstanciableClass.main(NonInstanciableClass.java:23)

如果该类可以实例化,同样的代码也适用于实例:

import java.lang.reflect.Field;

public class NonInstantiableClass {
    private Integer a1 = 1;
    private String a2 = "a";

    //private NonInstantiableClass () {
    //     throw new AssertionError();
    //}

    public static void printVariables () throws IllegalAccessException {

        for (Field field : NonInstantiableClass.class.getDeclaredFields()) {
            field.setAccessible(true);
            System.out.println(field.getName()
                    + " - " + field.getType()
                    + " - " + field.get(new NonInstantiableClass()));
        }
    }


    public static void main(String args[]) throws IllegalAccessException {
        NonInstantiableClass.printVariables();
    }
}

有更好的方法解决这个问题吗?

谢谢。

编辑:

正如Dylan指出的,如果类不可实例化,则无法初始化实例字段。当然,这些字段是静态的:

private static Integer a1 = 1;
private static String a2 = "a";

1
如果类没有实例化,那么值怎么可能被设置呢?除了使用 new 关键字之外,还有其他实例化对象的方法,有些可以绕过构造函数。但最终你必须要有一个对现有对象的引用。 - Dylan
你说得对 Dylan,他们本来就打算将它们设计成静态的。我错了,谢谢。 - Esteban S
我已经更新了我的答案,现在它符合你的要求。 - Dylan
1个回答

1

试试这个:

import java.lang.reflect.Field;

public class NonInstantiableClass {
    private static Integer a1 = 1;
    private static String a2 = "a";

    private NonInstantiableClass () {
         throw new AssertionError();
    }

    public static void printVariables () throws IllegalAccessException {

        for (Field field : NonInstantiableClass.class.getDeclaredFields()) {
            field.setAccessible(true);
            System.out.println(field.getName()
                    + " - " + field.getType()
                    + " - " + field.get(NonInstantiableClass.class));
        }
    }

    public static void main(String args[]) throws IllegalAccessException {
        NonInstantiableClass.printVariables();
    }
}

这只会告诉你静态字段的值。如果一个字段不是静态的,getVariableValue 将返回 null。

谢谢您的回复,很有趣,但是它没有填充字段。例如,使用 System.out.println(field.get(cl)); 打印它的值得到 null。尝试按照该解决方案,但我没找到如何填充它们。 - Esteban S
哦!我没意识到你在寻找它们的值,我的错。我也会试着调整一下。 - Dylan
我已经修复了,现在它会给你返回值。 - Dylan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接