[英]Performance/treatment of static references to class instances
我最近一直在嘗試以下Java模式,它幫助解決了一些代碼組織問題,但是我對最佳實踐,性能等存在多個疑問。
public class Example {
private static int[] somethingList = int[128];
public static final Example somethingOne = new Example(1);
public static final Example somethingTwo = new Example(2);
public static final ExampleChild somethingThree = new ExampleChild(3); // ExampleChild would extend Example
private Example( int id ){
// checks for existing id, etc
somethingList[id] = this;
}
public static Example getById( int id ){
return somethingList[id];
}
}
該類將事物列表注冊到靜態變量,但具有私有構造函數,該構造函數還將ID號列表保存到數組中。 Minecraft是在野外使用它的一個例子-對於他們的物品類別“注冊表”。
幾個問題:
Example.somethingOne
或Example.getById()
重新運行所有這些代碼,還是只運行一次? 也許我缺少對static
了解? somethingOne
是公開的,而不是僅僅通過ID調用它? 如果您有mods / plugins將自定義項目添加到列表中,但此處沒有按名稱靜態引用,則好像getById
是友好的。 如果在此之外的任何地方都沒有保存Example的單個實例,請調用Example.somethingOne或Example.getById()來重新運行所有這些代碼,還是只運行一次? 也許我缺少對靜態的一些了解?
不,靜態塊在類加載時運行,並綁定到代表類本身的java.lang.Class實例。
類是延遲加載的,但是一旦加載,就永遠不會在其類加載器的生存期內重新加載。
通過調用靜態方法或訪問靜態變量而不使用其實例不會造成性能損失。
您是否有任何理由想要公開someone的靜態實例,而不是僅通過id調用它? 如果您有mods / plugins將自定義項目添加到列表中,但此處沒有按名稱靜態引用,則好像getById是友好的。
您在這里回答了自己的問題。 通過一種方法運行訪問可以在將來添加模塊/插件或進行其他一些工作,而不必重構調用代碼。
但是,我可能希望實例成為靜態成員的一個原因是,如果調用代碼需要與特定實例而不是其他實例進行交互,而您只是希望您的類能夠控制那些實例,那么也許您可以添加新的實例。您想要的實例。
枚舉就是一個很好的例子。
對於動態枚舉,我已經使用了上面的確切模式,我想要的是一個枚舉,但是我需要某些實例屬於子類型,並且客戶不必擔心它。
因為調用私有構造函數的唯一位置是在somethingOne
和somethingTwo
的靜態聲明中,所以該構造函數將在第一次使用該類時被調用,這將觸發該類的加載和靜態代碼的執行。 。
這將在每次初始化類時執行,這意味着在典型情況下(使用Java提供的默認類加載),無論您訪問字段多少次,都只會調用一次。
您可能需要閱讀類和接口的JLS 12.4初始化和JVMS 5.5初始化 。
不確定為什么靜態實例是公共的,它們可以完全是私有的static final,並在第一次觸發類的初始化並獲得相同結果時調用getId方法。 在所有字段都是靜態字段和最終字段之后,也許這只是方便,所以為什么不提供對它們的直接訪問?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.