簡體   English   中英

為什么接口中的所有字段都是隱式靜態和最終的?

[英]Why are all fields in an interface implicitly static and final?

我只是想了解為什么 Interface 中定義的所有字段都是隱式staticfinal 保持字段static的想法對我來說很有意義,因為您不能擁有接口的對象,但為什么它們是final (隱式)?

任何人都知道為什么 Java 設計者要使接口中的字段成為staticfinal嗎?

接口旨在指定交互契約,而不是實現細節。 開發人員應該能夠僅通過查看接口來使用實現,而不必查看實現它的類內部。

接口不允許您創建它的實例,因為您不能指定構造函數。 所以它不能有實例狀態,盡管接口字段可以定義常量,這些常量是隱式靜態和最終的。

您不能在接口中指定方法主體或初始化程序塊,但從 Java 8 開始,您可以使用主體指定默認方法。 此功能旨在允許將新方法添加到現有接口,而無需更新所有實現。 但是,如果不首先創建實現接口的實例,您仍然無法執行這樣的方法。

旁白:請注意,您可以使用匿名內部類實現接口:

interface Foo {
    String bar();
}

class FooBar {
    Foo anonymous = new Foo() {
         public String bar() {
             return "The Laundromat Café";
    };
}

您必須為要編譯的匿名內部類提供接口的完整實現。

new Foo()正在使用其默認構造函數初始化匿名內部類。

final原因

如果字段未定義為 final,則任何實現都可以更改字段的值。 然后他們將成為實施的一部分。 接口是沒有任何實現的純規范。

static原因

如果它們是靜態的,那么它們屬於接口,而不是對象,也不屬於對象的運行時類型。

這里有幾個要點:

僅僅因為接口中的字段是隱式靜態 final 並不意味着它們必須是編譯時常量,甚至是不可變的。 您可以定義例如

interface I { String TOKEN = SomeOtherClass.heavyComputation(); JButton BAD_IDEA = new JButton("hello"); }

(請注意,在注釋定義中執行此操作可能會混淆 javac ,這與上述實際上編譯為靜態初始值設定項的事實有關。)

此外,這種限制的原因更多的是文體而不是技術,很多人希望看到它放松

字段必須是靜態的,因為它們不能是抽象的(就像方法一樣)。 因為它們不能是抽象的,所以實現者將無法在邏輯上提供字段的不同實現。

我認為這些字段必須是最終的,因為這些字段可能會被許多不同的實現者訪問,允許它們可變可能會出現問題(作為同步)。 還要避免它被重新實現(隱藏)。

只是我的想法。

我認為字段是 final 的要求是過度限制並且是 Java 語言設計者的錯誤。 有時,例如樹處理,當您需要在實現中設置常量時,需要在接口類型的對象上執行操作。 在實現類上選擇代碼路徑是一個麻煩事。 我使用的解決方法是定義一個接口函數並通過返回一個文字來實現它:

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

但是,使用此語法會更簡單、更清晰且不易出現異常實現:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}

規范、合同... 用於字段訪問的機器指令使用對象地址加上字段偏移量。 由於類可以實現許多接口,因此無法使非最終接口字段在擴展此接口的所有類中具有相同的偏移量。 因此必須實現不同的字段訪問機制:兩次內存訪問(獲取字段偏移量,獲取字段值)而不是一次加維護一種虛擬字段表(類似於虛擬方法表)。 猜猜他們只是不想讓 jvm 復雜化,因為這些功能可以通過現有的東西(方法)輕松模擬。

在 Scala 中,我們可以在接口中有字段,盡管在內部它們是按照我上面解釋的(作為方法)實現的。

static

Java 中任何static (變量或方法)都可以作為Classname.variablenameClassname.methodname或直接調用。 僅使用對象名稱調用它不是強制性的。

在接口中,不能聲明對象,而static使得可以通過類名調用變量而無需對象名。

final

它有助於保持變量的恆定值,因為它不能在其子類中被覆蓋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM