Java8常量池常量依赖项

Java8常量池常量依赖项,java,java-8,jvm,inline,java-bytecode-asm,Java,Java 8,Jvm,Inline,Java Bytecode Asm,假设我在文件a.java中定义了一个常量int: public final static int CONSTAN_VALUE_IN_A = 0; 当我在另一个文件B.java中使用此值时: int fooBValue = A.CONSTAN_VALUE_IN_A; 在我完成我的项目后,在B.class中,我有: fooBValue = 0 我想知道当我只有没有源代码的B.class文件时,值“0”从哪里来(A.java)。 我听说在使用java8编译时,通过读取B.class中的常量池,我

假设我在文件a.java中定义了一个常量int:

public final static int CONSTAN_VALUE_IN_A = 0;
当我在另一个文件B.java中使用此值时:

int fooBValue = A.CONSTAN_VALUE_IN_A;
在我完成我的项目后,在B.class中,我有:

fooBValue = 0
我想知道当我只有没有源代码的B.class文件时,值“0”从哪里来(A.java) 我听说在使用java8编译时,通过读取B.class中的常量池,我可以知道B.java在A.java中使用了一些常量值。 但我不确定如何通过读取常量池来获取常量的实际类。

几乎肯定不是

许多静态最终值甚至在编译时被与常量关联的实际值替换

static final int X = 0;
static final int Q = 9;

private void test(String[] args) {
    int x = X;
    int y = Q;
}
可能在汇编的早期阶段转变为:

private void test(String[] args) {
    int x = 0;
    int y = 9;
}
因此,发现该值实际来源的可能性非常小。

定义了一个“常量变量”,如下所示:

常量变量是使用常量表达式(§15.28)初始化的基元类型或字符串类型的最终变量

描述如何在类文件中结束这些操作:

三,。对常量变量(§4.12.4)字段的引用必须在编译时解析为常量变量初始值设定项表示的值V

如果这样的字段是静态的,那么二进制文件中的代码中不应该存在对该字段的引用,包括声明该字段的类或接口。此类字段必须始终显示为已初始化(§12.4.2);绝对不能遵守字段的默认初始值(如果不同于V)

A

    public final static int CONSTAN_VALUE_IN_A = 0;
满足常量变量的定义,因此在类
B
中使用时

    int fooBValue = A.CONSTAN_VALUE_IN_A;
该值在编译时解析。类
B
中未出现对
A.CONSTAN\u值的引用,而是将
0
的解析值编译到类B中

因此,不,除非您能找到源代码,否则无法判断
B
中的值来自何处

如果您不喜欢此行为,可以通过更改内容以避免不满足JLS 4.12.4的条件来避免此行为,例如使其不是最终的,或者更改类型以使其既不是基元也不是字符串。但是,使其不是常量变量的最简单方法是将初始化移到静态初始化器中:

    public final static int CONSTAN_VALUE_IN_A;
    static {
        CONSTAN_VALUE_IN_A = 0;
    }

顺便说一下,这在Java8中并不新鲜;这种行为已经有很长一段时间了。

我想知道我是否可以得到值“0”来自哪里
你的确切意思是什么?值是一个值,它不能“来自”。对于引用类型变量来说,有一种谈论相同值的感觉,但不是在这个上下文中。@拖拉者“来自”是指这个常量值的定义位置。@Andremoniy是的,有点像引用,我只是想知道当我阅读B.class文件时,如何知道值0“来自”a.class。请原谅我的表达能力不足。@Raymond,你不是自己定义的吗?因为你的问题说明了这一点,比如说我在a.java文件中定义了一个常量int;你的答案归结起来几乎肯定不是。他们在问题中已经提到的其余部分:在我编译了我的项目之后,在B.class中,我有[…]。@Andremoniy-我对“0”的解释是想知道值“0”是从哪里来的(A.java)是否可以告诉我
fooBValue
(即
0
)的结果值来自
A
类。@SotiriosDelimanolis-正是我的观点-源代码在类文件生成之前确实运行良好,在运行时肯定不可用。我的观点是你只是重复他们已经说过的内容,而你做得不令人信服。编辑你的答案,提供证据,而不是猜测,几乎可以肯定,可能性很小,很可能。从iirc的第一个版本开始。在Java1.1中,确实是这样的。所以,对于B.class文件,我无法理解它引用了A.class中定义的某个常量值,对吗?@Raymond Guo:没错。