Java:无法在枚举中使用枚举集:初始化错误:技术研究人才树示例
错误: -->下一行就是它崩溃的地方Java:无法在枚举中使用枚举集:初始化错误:技术研究人才树示例,java,casting,enums,initialization,Java,Casting,Enums,Initialization,错误: -->下一行就是它崩溃的地方 public enum BuildingTechTree { //Name SoftName Requirements NONE ("NULL", null), 将EnumSet.of(NONE)和EnumSet.of(BARRACKS)替换为null,可以让初始化工作,但由于缺少数据结
public enum BuildingTechTree {
//Name SoftName Requirements
NONE ("NULL", null),
将EnumSet.of(NONE)和EnumSet.of(BARRACKS)替换为null,可以让初始化工作,但由于缺少数据结构,会中断我的代码。。。很明显,但我这样做是为了测试我的代码的其余部分并不是原因
删除EnumSet.of(NONE)并替换为NONE,对于BARRACKS也是如此,更改所有相关的变量、构造函数和方法,这些都不起作用。。。(甚至无法使用contains.all,因为它“不适用于我更改的变量”…)
我使用第二个实现扩展了这个示例:
我还试图通过逐字复制示例来追溯我的步骤。增加
BARRACKS ("Barracks", EnumSet.of(NONE),
WALLS_SANDBAGS ("Sandbag wall", EnumSet.of(NONE),
POWERPLANT ("Power plant", EnumSet.of(BARRACKS)),
GUARDTOWER ("Guard Tower", EnumSet.of(BARRACKS));
静止
这导致了相同的“非枚举”错误。我没有任何代表,评论他的回答,指出初始化错误
添加了两个当前答案的信息,因为两个解决方案都会导致相同的新错误:
public boolean researchTech(BuildingTechTree tech) {
公共类技术树{
私有静态集techsKnown;
公共树木(){
techsKnown=EnumSet.of(BuildingTechTree.NONE);//使用此
techsKnown=EnumSet.noneOf(BuildingTechTree.class);//或此
}
公共静态布尔研究技术(BuildingTechTree技术){
if(techsKnown.containsAll(tech.requirements)){//导致空指针
返回true;//异常@techsKnown
}
返回false;
}
您遇到了鸡和蛋的问题。您可以将枚举重构为如下内容:
public class TechTrees {
private static Set<BuildingTechTree> techsKnown;
public TechTrees() {
techsKnown = EnumSet.of(BuildingTechTree.NONE); //Using this
techsKnown = EnumSet.noneOf(BuildingTechTree.class); //Or this
}
public static boolean researchTech(BuildingTechTree tech) {
if (techsKnown.containsAll(tech.requirements)) { //Causes null pointer
return true; //exception @ techsKnown
}
return false;
}
public enum BuildingTechTree{
无(“空”),
营房(“营房”),
墙壁和沙袋(“沙袋墙”),
发电厂(“发电厂”),
警卫塔(“警卫塔”);
静止的{
NONE.trees=EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees=EnumSet.of(无);
墙\沙袋。树=枚举集(无);
POWERPLANT.trees=兵营的枚举集;
GUARDTOWER.trees=兵营的枚举集;
}
私有字符串名称;
私人树木;
私有BuildingTechTree(字符串名称){
this.name=名称;
}
公共字符串getName(){
返回名称;
}
公共集getTrees(){
返回集合。不可修改集合(树);
}
}
编辑:
关于你的第二个问题:你正在从一个静态方法访问一个静态变量。但是这个变量在类的构造函数被调用时被初始化(这是一个巨大的设计问题)。不要使用非最终静态字段。也不要从实例方法或构造函数初始化静态字段。这没有意义。在构造汽车时,您没有设置所有汽车应具有的颜色。静态初始化静态字段:
public enum BuildingTechTree {
NONE("NULL"),
BARRACKS("Barracks"),
WALLS_SANDBAGS("Sandbag wall"),
POWERPLANT("Power plant"),
GUARDTOWER("Guard Tower");
static {
NONE.trees = EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees = EnumSet.of(NONE);
WALLS_SANDBAGS.trees = EnumSet.of(NONE);
POWERPLANT.trees = EnumSet.of(BARRACKS);
GUARDTOWER.trees = EnumSet.of(BARRACKS);
}
private String name;
private Set<BuildingTechTree> trees;
private BuildingTechTree(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<BuildingTechTree> getTrees() {
return Collections.unmodifiableSet(trees);
}
}
公共类技术树{
已知专用静态最终设置技术=
EnumSet.of(BuildingTechTree.NONE);
公共静态布尔研究技术(BuildingTechTree技术){
返回已知技术,包括所有(技术要求);
}
}
您的声明结构非常聪明,很遗憾它不起作用。但是EnumSet
显然需要首先对enum进行完全初始化。它尝试从enum获取常量数组,以便知道内部位集需要多少空间
这里有一个解决方法。它使用一个helper方法,首先创建一个普通集合(HashSet
),然后在静态初始化块中,它迭代枚举常量并用EnumSet
替换所有集合
public class TechTrees {
private static final Set<BuildingTechTree> TECHS_KNOWN =
EnumSet.of(BuildingTechTree.NONE);
public static boolean researchTech(BuildingTechTree tech) {
return TECHS_KNOWN.containsAll(tech.requirements));
}
}
public enum BuildingTechTree{
//命名常数
//名称SoftName要求
无(“空”,空),
营房(“营房”,一套(无)),
墙壁和沙袋(“沙袋墙”,一套(无)),
发电厂(“发电厂”,一套(营房)),
警卫塔(“警卫塔”,一套(兵营));
私有最终字符串softName;
私人设置要求;
私有BuildingTechTree(字符串softName,设置要求){
this.softName=softName;
本节要求=要求;
}
私有静态集合(BuildingTechTree…值){
返回新的HashSet(Arrays.asList(values));
}
静止的{
对于(BuildingTechTree v:values()){
如果(v.requirements==null){
v、 需求=EnumSet.noneOf(BuildingTechTree.class);
}否则{
v、 需求=枚举集.copyOf(v.requirements);
}
}
}
}
没有更多初始化错误,但是使用私有静态集techsKnown;techsKnown=EnumSet.of(BuildingTechTree.NONE);会导致techsKnown为null,因为它仍在为NONE复制原始“null”值,似乎不是深度副本…将尝试创建另一个“转换器”作为你的,只是为了this@user48573我不知道你的意思。它很好用。它不需要是“深度复制”因为所有枚举常量都是单例的。请参阅添加到question@user48573这个问题是因为techsKnown
是一个静态变量,它只在实例构造函数中初始化,你大概不会调用它。我自己也得出了同样的结论,我打算自己更正,但你打败了不管怎样,标记为答案和+1是因为,你的答案不需要我编辑一大堆其他代码,解释了原因,没有使用抽象的想法,并解释了你添加/更改的代码的作用。(哦,还有一个补充,即使我复制了声明),以及回答后的持续支持。谢谢,非常感谢,希望许多人能从阅读此问题中获得一些收获/a
public enum BuildingTechTree {
NONE("NULL"),
BARRACKS("Barracks"),
WALLS_SANDBAGS("Sandbag wall"),
POWERPLANT("Power plant"),
GUARDTOWER("Guard Tower");
static {
NONE.trees = EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees = EnumSet.of(NONE);
WALLS_SANDBAGS.trees = EnumSet.of(NONE);
POWERPLANT.trees = EnumSet.of(BARRACKS);
GUARDTOWER.trees = EnumSet.of(BARRACKS);
}
private String name;
private Set<BuildingTechTree> trees;
private BuildingTechTree(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<BuildingTechTree> getTrees() {
return Collections.unmodifiableSet(trees);
}
}
public class TechTrees {
private static final Set<BuildingTechTree> TECHS_KNOWN =
EnumSet.of(BuildingTechTree.NONE);
public static boolean researchTech(BuildingTechTree tech) {
return TECHS_KNOWN.containsAll(tech.requirements));
}
}
public enum BuildingTechTree {
// Named constants
//Name SoftName Requirements
NONE ("NULL", null),
BARRACKS ("Barracks", setOf(NONE)),
WALLS_SANDBAGS ("Sandbag wall", setOf(NONE)),
POWERPLANT ("Power plant", setOf(BARRACKS)),
GUARDTOWER ("Guard Tower", setOf(BARRACKS));
private final String softName;
private Set<BuildingTechTree> requirements;
private BuildingTechTree(String softName, Set<BuildingTechTree> requirements) {
this.softName = softName;
this.requirements = requirements;
}
private static Set<BuildingTechTree> setOf(BuildingTechTree... values) {
return new HashSet<>(Arrays.asList(values));
}
static {
for (BuildingTechTree v : values()) {
if (v.requirements == null) {
v.requirements = EnumSet.noneOf(BuildingTechTree.class);
} else {
v.requirements = EnumSet.copyOf(v.requirements);
}
}
}
}