静态块和具有静态非原始数据字段的 Field.get(null)

发布于 2024-12-15 05:11:32 字数 1468 浏览 3 评论 0原文

我有以下类:

public class A {

    static {
        B.load(A.class);
    }

    public static final C field1 = new C("key1", "value1");

    public static final C field2 = new C("key2", "value2");

    public static void main(String[] args) {
        System.out.println(A.field1);
    }

}

and

public class B {

    public static void load(Class<?> clazz) {
        for (Field field : clazz.getFields()) {
            try {
                System.out.println("B.load -> field is " + field.get(null));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

}

and

public class C {

    private final String key;

    private final String value;

    public C(String key, String value) {
        super();
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return this.key;
    }

    public String getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return "C [key=" + this.key + ", value=" + this.value + "]";
    }

}

当执行 A 时,我得到:

B.load -> field is null
B.load -> field is null
C [key=key1, value=value1]

为什么 field.get(null) 在执行时返回 null 值?我没有遇到任何异常,而且 Javadoc 似乎没有解释这种行为。

I have the following classes:

public class A {

    static {
        B.load(A.class);
    }

    public static final C field1 = new C("key1", "value1");

    public static final C field2 = new C("key2", "value2");

    public static void main(String[] args) {
        System.out.println(A.field1);
    }

}

and

public class B {

    public static void load(Class<?> clazz) {
        for (Field field : clazz.getFields()) {
            try {
                System.out.println("B.load -> field is " + field.get(null));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

}

and

public class C {

    private final String key;

    private final String value;

    public C(String key, String value) {
        super();
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return this.key;
    }

    public String getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return "C [key=" + this.key + ", value=" + this.value + "]";
    }

}

When A is executed I get:

B.load -> field is null
B.load -> field is null
C [key=key1, value=value1]

Why does field.get(null) return a null value when it is executed? I get no exception and it seems that this behavior is not explained by the Javadoc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故人的歌 2024-12-22 05:11:32

我相信所有静态成员都将按声明顺序执行(对于静态块)和初始化(对于静态字段)。尝试将类 A 的静态块放在类的末尾,或者至少放在静态字段之后。让我知道这是否有影响。

编辑:有关原语和字符串行为的信息...

当您有一个最终静态字段是原语或字符串文字(或可以静态评估导致其中之一的表达式)时,它被认为是编译 -时间常数。基本上,设置这样的值不需要“计算”,例如调用构造函数或评估可能尚未初始化的其他字段。尽管字符串不是基元,但它们在编译时受到特殊处理,以使代码中的字符串文字成为可能。

这意味着一旦类被加载并准备好初始化,就可以分配这些字段。尽管我不知道与此相关的规范细节,但反射实验表明这肯定会发生。

Java 语言规范的以下部分与理解此行为相关:

I believe all static members will be executed (for static blocks) and initialized (for static fields) in declaration order. Try placing the static block of class A at the end of the class, or at least after the static fields. Lemme know if that makes a difference.

EDIT: info regarding the behaviour for primitives and Strings...

When you have a final static field that is a primitive or a String literal (or an expression that can be statically evaluated that results in one of these), it's considered a compile-time constant. Basically, setting such a value does not require "computation", like invoking a constructor or evaluating vis-a-vis other fields that may not have been initialized yet. Although Strings aren't primitives, they're given a special treatment in compilation to make String literals in code a possibility.

This means such fields can be assigned as soon as a class has been loaded and is ready for initialization. Although I don't know the specification details regarding that, experimenting with reflection shows that this is what must be happening.

Following sections of the Java language specification are relevant to understanding this behaviour:

染火枫林 2024-12-22 05:11:32

在类 A 中,您必须在调用静态函数之前声明静态字段。

public static final C field1 = new C("key1", "value1");

public static final C field2 = new C("key2", "value2");

static {
    B.load(A.class);
}

Java 教程对此进行了解释:

一个类可以有任意数量的静态初始化块,它们可以出现在类主体中的任何位置。运行时系统保证静态初始化块按照它们在源代码中出现的顺序被调用。

In your class A you have to declare the static fields before the call to your static function.

public static final C field1 = new C("key1", "value1");

public static final C field2 = new C("key2", "value2");

static {
    B.load(A.class);
}

The Java tutorial explains it:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文