2017-09-13 50 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