[英]initialize static final variable in child class(sub class) in java
我有一個這樣的課程:
public abstract class A {
public static final int FIELD;
// some methods
}
我想在子類中初始化變量 FIELD。 我的意思是這樣的:
public class B extends A {
FIELD = 5;
}
編輯實際上我有多個類擴展 A 並且所有類都有變量 FIELD 但具有不同的值; 所以我發現的方法是重構變量 FIELD 並在超類中聲明它。 還有其他解決方案嗎? 有可能有這樣的東西嗎? 感謝您的幫助。
關鍵是超類的子類沒有在超類中聲明的靜態字段的副本,並且超類在它們之間共享; 所以沒有辦法讓靜態變量在不同的子類中具有不同的值。 因此,我將在所有子類中聲明變量 FIELD。
我在評論中從@LenceJava 得到了所有這些。 謝謝@LanceJava。
不,這是不可能的(至少不是沒有一些嚴重的骯臟技巧)
當A
被初始化時,該字段必須被初始化。 A
在B
初始化之前被初始化。 B
任何內容僅在B
初始化時或之后執行。
如果這是可能的,在加載 B 之前使用A.FIELD
會發生什么?
您可以做的是將字段設為私有而不是靜態的,並提供一個只允許對其進行一次調用並從B
調用它的設置器。
在像這樣的大多數情況下,真正的問題有一個更清晰的解決方案,但是由於您沒有提到您嘗試解決的真正問題,我們在這方面無能為力。
由於它是static
和final
,因此在初始化時和/或在 static 塊中,您可以為該變量賦值。 只是沒有其他地方。
當你創建一個新的B
對象,首先,新的A
對象將被自動創建,其最終的變量已其默認的構造函數初始化; 所以你不能再修改它們的值。
final
變量在聲明時初始化,並且不能在子類中重新初始化或修改。 java中的final
表示常量。 嘗試修改它們的值會導致編譯錯誤。
如果要在派生類中更改它們,則不能在最終類中使用靜態最終變量。
1) 刪除 FIELD 屬性的 final 關鍵字
2)修改代碼如下
import java.io.*;
import java.util.*;
class A {
public static int FIELD = 4;
}
class B extends A {
public B(){
this.FIELD = 5;
}
}
public class Test {
public static void main(String args[]) throws Exception {
B b = new B();
System.out.println("B value:"+b.FIELD);
}
}
輸出是:
B value:5
不管 final 關鍵字是什么,單個靜態變量不適用於多個子類,因為每當實例化新子類時都會重新分配單個靜態變量。 此外,實例化的順序仍然會進一步混淆最后靜態更新的值。
jshell> public abstract class A { public static String STATIC_SUPER_VAR = "A"; }
| created class A
jshell> public class B extends A { public B() { STATIC_SUPER_VAR = "B"; } }
| created class B
jshell> B.STATIC_SUPER_VAR
$3 ==> "A"
jshell> A.STATIC_SUPER_VAR
$4 ==> "A"
jshell> new B()
$3 ==> B@685cb137
jshell> B.STATIC_SUPER_VAR
$4 ==> "B"
jshell> A.STATIC_SUPER_VAR
$5 ==> "B"
jshell> public class C extends A { public C() { STATIC_SUPER_VAR = "C";} }
| created class C
jshell> new C()
$7 ==> C@5f2108b5
jshell> A.STATIC_SUPER_VAR
$8 ==> "C"
jshell> B.STATIC_SUPER_VAR
$9 ==> "C"
jshell> C.STATIC_SUPER_VAR
$10 ==> "C"
我們可以使用靜態 Map 而不是單個靜態變量。
jshell> public abstract class A {
...>
...> private static Map<Class<? extends A>, Integer> CLASS_FIELD_HOLDER = new HashMap<>();
...>
...> public A (int classSpecificInteger) {
...>
...> CLASS_FIELD_HOLDER.put(getClass(), classSpecificInteger);
...> }
...>
...>
...> public static int getClassSpecificInteger(Class<? extends A> clazz) {
...>
...> return CLASS_FIELD_HOLDER.get(clazz);
...> }
...> }
| created class A
jshell> public class B extends A {
...>
...> public B (int classSpecificInteger) {
...>
...> super(classSpecificInteger);
...> }
...> }
| created class B
jshell> public class C extends A {
...>
...> public C (int classSpecificInteger) {
...>
...> super(classSpecificInteger);
...> }
...> }
| created class C
確保子類已初始化,我的意思是在訪問之前更新靜態地圖,否則 NPE
jshell> B.getClassSpecificInteger(B.class)
| Exception java.lang.NullPointerException
| at A.getClassSpecificInteger (#5:13)
| at (#7:1)
現在初始化:
jshell> new B(10);
$8 ==> B@610694f1
jshell> new C(20)
$9 ==> C@50b494a6
現在靜態訪問它,子類中沒有 FIELD:
jshell> B.getClassSpecificInteger(B.class)
$10 ==> 10
jshell> A.getClassSpecificInteger(B.class)
$11 ==> 10
jshell> B.getClassSpecificInteger(C.class)
$12 ==> 20
這應該有效。
public class A {
public final int FIELD;
A(int a){
this.FIELD=a;
}
}
public class B extends A {
B(int a){
super(a);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.