[英]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.