Java 为enum-s提供公共数据的更好方法
假设,我希望一个int[]数组由enum的所有实例共享。这里有一个例子Java 为enum-s提供公共数据的更好方法,java,enums,Java,Enums,假设,我希望一个int[]数组由enum的所有实例共享。这里有一个例子 public enum SampleEnum { Enum1(1), Enum2(2), Enum3(3), Enum4(4); private int[] values; private static final int[] SharedValues = {1, 2, 3, 4, 5}; private static final int ValueCount = SharedValues
public enum SampleEnum {
Enum1(1), Enum2(2), Enum3(3), Enum4(4);
private int[] values;
private static final int[] SharedValues = {1, 2, 3, 4, 5};
private static final int ValueCount = SharedValues.length;
private SampleEnum(int factor) {
// I prefer to calculate data once within constructor
values = new int[ValueCount];
for (int i=0; i<ValueCount; i++)
values[i] = SharedValues[i] * factor;
}
private int[] getValues() {
return values;
}
}
public enum SampleEnum{
枚举1(1)、枚举2(2)、枚举3(3)、枚举4(4);
私有int[]值;
私有静态final int[]SharedValue={1,2,3,4,5};
私有静态最终int-ValueCount=SharedValues.length;
私有样本数(整数因子){
//我更喜欢在构造函数中计算一次数据
值=新整数[ValueCount];
对于(int i=0;i
在枚举初始值设定项中不允许引用静态类有什么原因吗
这是一个不允许访问的静态字段,有一个很好的理由:该字段仍将有其初始值,因为枚举成员将在以后的任何静态字段初始值设定者之前初始化。如果您试图填充由枚举的某些方面设置键的映射,这通常是一个问题-您确实希望执行在构造函数中填充,但您不能,因为映射尚未创建
选项:
- 在静态初始化程序块中执行所有
值
初始化,该初始化程序块在构建所有实例后执行。这里的问题是,如果希望字段为最终字段,则需要首先创建数组,这意味着知道数组的大小,而无需访问数据。(请注意,values()
方法在这里也可用,因此您选择的名称在这里是不幸的。)
- 使用私有嵌套类作为静态字段初始化的“持有者”。这类似于第二种解决方案,但不公开该类
老实说,后一种方法可能是最简单的
public enum SampleEnum {
...
private static class SampleEnumData {
static final int[] SHARED_VALUES = {1, 2, 3, 4, 5};
}
}
只想提供另一个例子。我试图创建一个字段的偏移/长度字典,它保证了唯一的名称,并且对移动的字段有弹性,在中间添加新的,等等。
我在尝试引用偏移量时遇到“无法访问静态字段”,如下所示:
enum Fields1 {
FIELD1(4), FIELD2(1), FIELD3(8), FIELD4(8);
private static int nextOfs = 0;
public final int size;
public final int offset;
private Fields1(int size) {
this.size = size;
this.offset = nextOfs; // Cannot refer to the static enum field Fields1.nextOfs within an initializer
nextOfs += size; // Same here
}
}
在阅读了这篇文章及其答案后,我转向以下内容:
enum Fields {
FIELD1(4), FIELD2(1), FIELD3(8), FIELD4(8);
public final int size;
public final int offset;
private Fields(int size) {
this.size = size;
this.offset = OffsetAllocator.FieldsAllocator.getNextOfs(size);
}
private static final class OffsetAllocator {
private static final OffsetAllocator FieldsAllocator = new OffsetAllocator();
private int nextOfs = 0;
private final int getNextOfs(int size) {
int ofs = nextOfs;
nextOfs += size;
return ofs;
}
}
}
构造函数是在静态字段全部初始化之前调用的,请参见谢谢,J.Rush。据我所知,所有类都是这样,而不仅仅是enum-s。元素的第一次实例化会触发静态构造函数并初始化所有静态字段。为什么enum有一个特殊的限制?感谢您提供了如此广泛的注释在我看来,这不是一个有效的解决方案,因为每次都会重新计算偏移量(好像以前什么都没有发生过!)。更合理的方法(我的帖子建议)是在不同的类(比如OffsetClass)中将nextOfs作为静态字段,因此您可以保留原始代码,仅将nextOfs替换为OffsetClass。nextOfs。在重新计算的一开始,我就失去了您……偏移量/大小成员是最终的,并初始化了一次。多次访问FIELD1.offset将不会重新计算任何内容……或者您正在谈论其他内容?
enum Fields {
FIELD1(4), FIELD2(1), FIELD3(8), FIELD4(8);
public final int size;
public final int offset;
private Fields(int size) {
this.size = size;
this.offset = OffsetAllocator.FieldsAllocator.getNextOfs(size);
}
private static final class OffsetAllocator {
private static final OffsetAllocator FieldsAllocator = new OffsetAllocator();
private int nextOfs = 0;
private final int getNextOfs(int size) {
int ofs = nextOfs;
nextOfs += size;
return ofs;
}
}
}