tl;博士
作为一种解决方法,使用 switch expression 返回硬编码集。
enum Species
{
CAT, DOG, BAT, PIG, RAT, ANT;
public Set < Species > afraidOf ( )
{
return switch ( this )
{
case CAT -> Set.of();
case DOG -> Set.of( CAT , RAT );
case BAT -> Set.of( DOG );
case PIG -> Set.of( BAT , DOG );
case RAT -> Set.of( DOG , PIG );
case ANT -> Set.of( RAT );
};
}
}
用法:
System.out.println( Species.DOG.afraidOf() );
[猫,老鼠]
详情
这是 Java 的一个有趣的部分。
您似乎可以将枚举的元素传递给同一枚举的构造函数。比如这样:
package work.basil.animal;
import java.util.Set;
public class App3
{
public static void main ( String[] args )
{
enum Species
{
CAT( Set.of() ),
DOG( Set.of( CAT ) ),
BAT( Set.of( DOG ) ),
PIG( Set.of( BAT , DOG ) ),
RAT( Set.of( DOG , PIG ) ),
ANT( Set.of( RAT ) );
Set < Species > afraidOf;
Species ( Set < Species > afraidOf )
{
this.afraidOf = afraidOf;
}
}
System.out.println( Species.DOG.afraidOf );
}
}
非法前向引用错误
但是您不能进行“前向引用”。所以我们不能满足你让狗害怕老鼠的愿望,因为当狗的构造函数运行时,RAT 实例还没有被创建。
所以下面的代码失败了:
CAT( Set.of() ),
DOG( Set.of( CAT , RAT ) ), // <--- Error: Illegal forward reference.
BAT( Set.of( DOG ) ),
PIG( Set.of( BAT , DOG ) ),
RAT( Set.of( DOG , PIG ) ),
ANT( Set.of( RAT ) );
解决方法:使用 switch 表达式进行硬编码
一种解决方法是添加一个方法afraidOf,它返回一个集合(或数组,等等)。使用switch expression 压缩代码。
package work.basil.animal;
import java.util.Set;
public class App3
{
public static void main ( String[] args )
{
enum Species
{
CAT, DOG, BAT, PIG, RAT, ANT;
public Set < Species > afraidOf ( )
{
return switch ( this )
{
case CAT -> Set.of();
case DOG -> Set.of( CAT , RAT );
case BAT -> Set.of( DOG );
case PIG -> Set.of( BAT , DOG );
case RAT -> Set.of( DOG , PIG );
case ANT -> Set.of( RAT );
default -> Set.of(); // Or throw an exception here, your choice.
};
}
}
System.out.println( Species.DOG.afraidOf() );
}
}
[猫,老鼠]
编译器检查所有情况
您的 IDE 可能会指出 default 在现代 Java 中是不必要的。
如果您向枚举添加一个新元素,例如COW,或者您从 switch 表达式中删除一个 case,编译器会警告您错误“'switch' 表达式不涵盖所有可能的输入值”。
所以下面的代码就足够了。我们可以放心,我们已经涵盖了所有案例。
return switch ( this )
{
case CAT -> Set.of();
case DOG -> Set.of( CAT , RAT );
case BAT -> Set.of( DOG );
case PIG -> Set.of( BAT , DOG );
case RAT -> Set.of( DOG , PIG );
case ANT -> Set.of( RAT );
};
EnumSet
EnumSet 类是Set 的专门实现,针对枚举对象进行了优化。 EnumSet 非常高效,占用内存少,执行速度非常快。
您可以使用EnumSet.of 而不是Set.of 来优化我们的解决方案。但请注意,在 Java 的某些实现中,Set.of 方法可能足够聪明,可以自行进行优化并返回一个EnumSet 作为其Set 对象。
return switch ( this )
{
case CAT -> EnumSet.noneOf( Species.class );
case DOG -> EnumSet.of( CAT , RAT );
case BAT -> EnumSet.of( DOG );
case PIG -> EnumSet.of( BAT , DOG );
case RAT -> EnumSet.of( DOG , PIG );
case ANT -> EnumSet.of( RAT );
};
EnumSet 是可修改的。所以如果你想要unmodifiable,坚持使用Set.of。
我在这里使用Set,因为这是我自己的偏好。但是,如果您坚持,我希望您可以仅对数组使用相同的代码。