2017-09-13 81 views
-2

比方说,我在文件中A.java定义的常量INT:当我用在另一个文件B.java这个值的Java 8常量池常数依赖

public final static int CONSTAN_VALUE_IN_A = 0; 

int fooBValue = A.CONSTAN_VALUE_IN_A; 

后,我编译我的项目,在B.class,我有:

fooBValue = 0 

我想知道如果我能得到其中的值“0”来自(A.java)当我只有B.class文件没有源代码。 我听说用java8编译时,通过读取B.class中的常量池,我可以知道B.java在A.java中使用了一些常量值。 但我并不确定这一点,或者如何通过阅读常量池来获得常量来自实际的类。

+1

'我想知道如果我能得到值“0”来自哪里“你究竟是什么意思? – procrastinator

+1

价值是一种价值,它不能“来自”。关于引用类型变量有相同的值的说法,但不是在这种情况下。 – Andremoniy

+0

@procrastinator“来自”意味着定义了这个常量值。 –

回答

-1

几乎肯定不是。

许多static final值甚至在编译时被与常量相关的实际值所替代。

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; 
} 

所以发现的,其中的价值实际上是来自于机会是非常

+0

虽然我不是你的回答,但对我来说,这个问题本身没有任何意义; – Andremoniy

+0

你的答案归结为_几乎肯定不是._他们已经在他们的问题中提到的其他问题:_在我编译我的项目之后,在B.class中,我有[...] _。 –

+0

@Andremoniy - 我对*的解释我想知道如果我可以得到值“0”来自哪里(A.java)* OP是否可以告诉'fooBValue'(即'0')的结果值来自来自'A'类。 – OldCurmudgeon

3

JLS 4.12.4定义了一个“常量变量”如下:

常量变量是与一个常量表达式(§15.28)初始化基本类型或String类型的最终变量。

JLS 13.1描述如何这些最终在类文件中:

3.一个字段的引用是一个常量变量(§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_VALUE_IN_A,而解析值0被编译到B类中。

所以,不,没有办法知道B的值来自哪里,除非你能找到源代码。

如果你不喜欢这种行为,你可以通过改变东西来避免它,这样就不会满足JLS 4.12.4的条件,比如使它不是最终的,或者通过改变类型以使它成为既不是原始也不是String。然而,使它不是一个常数变量的最简单的方法是将初始化移动到一个静态初始化:

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

顺便说一句,这不是用Java 8新;这种行为已经有很长一段时间了。

+1

自第一版iirc以来。在Java1.1中,确实如此。 – Holger

+0

所以,用B.class文件,我无法弄清楚它引用了在A.class中定义的一些常量值,对吧? –

+0

@雷蒙德郭:确切地说。 – Holger