我刚刚失去了几个小时调试我的应用程序,我相信我偶然发现了一个(另一个o_O)Java bug ...嗅...我希望它不是,因为这会很难过:(
我正在做以下事情:
mask使用一些标志创建EnumSetObjectOutputStream.writeObject(mask))mask预期结果:第二个序列化对象与第一个序列化对象不同(反映实例中的更改)
获得的结果:第二个序列化对象是第一个的精确副本
代码:
enum MyEnum {
ONE, TWO
}
@Test
public void testEnumSetSerialize() throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(bos);
EnumSet<MyEnum> mask = EnumSet.noneOf(MyEnum.class);
mask.add(MyEnum.ONE);
mask.add(MyEnum.TWO);
System.out.println("First serialization: " + mask);
stream.writeObject(mask);
mask.clear();
System.out.println("Second serialization: " + mask);
stream.writeObject(mask);
stream.close();
ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
System.out.println("First deserialized " + istream.readObject());
System.out.println("Second deserialized " + istream.readObject());
}
Run Code Online (Sandbox Code Playgroud)
它打印:
Run Code Online (Sandbox Code Playgroud)First serialization: …
在Java方法中指定标志的最佳做法是什么?
我已经看到SWT使用int作为位域,如:
(部分来自"Effective Java,2nd Ed."第159页):
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
void printText(String text, int flags) {
}
}
Run Code Online (Sandbox Code Playgroud)
你的客户电话看起来像:
printText("hello", Text.STYLE_BOLD | Text.STYLE_ITALIC);
Run Code Online (Sandbox Code Playgroud)
..但是这是不鼓励的,因为你可以将来自不同类的标志(int值)混合在一起,而无需任何编译器检查.
在同一本书("Effective Java")中,我看到了EnumSet的使用,但随后您的用户调用变为:
printText("hello", EnumSet.of(Style.Bold, Style.ITALIC));
Run Code Online (Sandbox Code Playgroud)
我发现这有点冗长,我更喜欢SWT的优雅.
还有其他选择还是这基本上是你必须选择的两种口味?
这是Java,跨平台,并在运行Ubuntu Oneric的计算机上进行调试,OpenJDK作为我的运行时安装.
我有一个EnumSet用于检查我正在进行的游戏中的类内部.我有来自logcat的读数,来自我的构造函数中的debug aplenty:
Tile : passability being set...?
Exception in thread "Thread-1" javax.media.opengl.GLException:java.lang.NullPointerException
...
Caused by: java.lang.NullPointerException
at net.darkglass.map.Tile.addPassability(Tile.java:144)
...
Run Code Online (Sandbox Code Playgroud)
不好笑.跟踪它,我的问题似乎完全是这条线:
public void addPassability(Passability type)
{
this.passability.add(type);
}
Run Code Online (Sandbox Code Playgroud)
我指的是那个功能的主体.它从构造函数中调用为:
this.addPassability(Passability.AIR);
Run Code Online (Sandbox Code Playgroud)
发生NullPointerException时.在Passability Enum Type的主体中,我有
public enum Passability
{
AIR, ALL, GROUND, NONE, SIGHT, SKILL, STRUCTURE, WATER;
}
Run Code Online (Sandbox Code Playgroud)
就字面意思而言,整个枚举保存包声明.this.passability已声明
private EnumSet <Passability> passability;
Run Code Online (Sandbox Code Playgroud)
在类定义的开头,我的印象是add()方法作为Java标准中EnumSet定义的一部分继承.
我是自学成才,但我并不疯狂.要么我有错误,要么有更好的方法来做到这一点.那些有一些有用知识的人能够伸出援手吗?
旧的方式,如果我们想要switch一些复杂的位掩码,我们可以很容易地这样做(从我头顶的一个随机例子来证明问题):
private static final int MAN = 0x00000001;
private static final int WOMAN = 0x00000002;
// ...alive, hungry, blind, etc.
private static final int DEAD = 0xFF000000;
public void doStuff(int human) {
switch (human) {
case MAN | DEAD:
// do something
break;
// more common cases
}
}
Run Code Online (Sandbox Code Playgroud)
如今,因为我们使用enums和EnumSets,我有时喜欢做类似的事情:
enum Human {
MAN, WOMAN, DEAD; // etc.
}
public void doStuff(EnumSet human) {
switch (human) {
case Human.MAN | Human.DEAD:
// do something …Run Code Online (Sandbox Code Playgroud) 我有两个EnumSet.
EnumSet.of(A1, A2, A3);
EnumSet.of(A3, A4, A5, A6);
Run Code Online (Sandbox Code Playgroud)
我想找到两个集合中存在哪些值.(在这种情况下,A3.)
有没有快速的方法呢?
我想序列化一些EnumSet<FooType>,以String使用它的toString()方法.
例如:EnumSet.of(FooType.COMMON, FooType.MEDIUM).toString()会给[COMMON, MEDIUM].
问题是关于将这样的字符串反序列化为优雅的方法EnumSet<FooSet>.我正在寻找一些众所周知的库(可能是这样的apache-commons)或标准的Util-class来处理这类事情.
就像是: EnumSetUtil.valueOf(FooType.class, "[COMMON, MEDIUM]")
我用这样的方式实现了这个东西:
public static <E extends Enum<E>> EnumSet<E> valueOf(Class<E> eClass, String str) {
String[] arr = str.substring(1, str.length() - 1).split(",");
EnumSet<E> set = EnumSet.noneOf(eClass);
for (String e : arr) set.add(E.valueOf(eClass, e.trim()));
return set;
}
Run Code Online (Sandbox Code Playgroud)
但是,可能有现成的解决方案,或者这样做非常简单的方法.
我对 Kotlin 还很陌生,并尝试创建一种位集枚举,其中整数对应于状态,并且我可以通过切换各个位来切换各个状态。但我坚持认为对象可以没有状态。
import java.util.*
fun main() {
var d = Door(100, EnumSet.noneOf(Status))
}
enum class Status(intValue: Int) {
OPEN(1),
CLOSED(1 shl 1),
CRACKED(1 shl 2),
BROKEN(1 shl 3)
}
class Door(val id: Int, val status: EnumSet<Status>) {}
Run Code Online (Sandbox Code Playgroud)
此代码失败并出现错误Classifier 'Status' does not have a companion object, and thus must be initialized here
Status.class我正在读另一个问题,他们说在 内部使用EnumSet.noneOf,但这会引发更多错误。
我有实体人:
@Entity
@Table(schema="", name="PERSON")
public class Person {
List<PaymentType> paymentTypesList;
//some other fields
//getters and setters and other logic
}
Run Code Online (Sandbox Code Playgroud)
我有枚举PaymentType:
public enum PaymentType {
FIXED, CO_FINANCED, DETERMINED;
}
Run Code Online (Sandbox Code Playgroud)
如何持久化Person及其枚举列表(在此列表中我必须放置可变数量的枚举,可能有其中一个,或两个或全部)
我正在使用Spring和Postgres,实体是使用JPA注释创建的,并使用Hibernate进行管理.
以下代码在Eclipse中编译(并按预期运行测试):
import java.util.EnumSet;
public class EnumTest {
static enum Cloneables implements Cloneable {
One, Two, Three;
}
public <T extends Cloneable> T getOne(Class enumType) {
EnumSet<? extends T> set = EnumSet.allOf(enumType);
return set.iterator().next();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,javac直接或通过Maven 编译(JDK 7)失败,出现以下错误:
type argument ? extends T is not within bounds of type-variable E
Run Code Online (Sandbox Code Playgroud)
说实话,enums +接口+类型参数(泛型)的复杂性一下子就把我扔掉了,因为我正在编写代码,但我想我终于把它弄好了.
目标是编写这样的调用代码:
Cloneable something = enumTest.getOne(Cloneables.class);
Run Code Online (Sandbox Code Playgroud)
例如,在Eclipse中,以下测试编译并传递:
@Test
public void testGetFirst() {
assertSame(Cloneables.One, getOne(Cloneables.class));
}
Run Code Online (Sandbox Code Playgroud)
任何有关"正确",Eclipse或javac的线索都值得赞赏.
同样值得赞赏的是关于实现该想法的替代方法的任何建议:将类作为可以使用的方法参数,EnumSet.allOf()并且还确定Enum对象的类型.EnumSet
顺便说一下,不要打扰批评这种方法的目的; 我已经从更有用/有意义的代码中减少了它.我对讨论"从枚举类型中找到第一个元素"的优点不感兴趣 - 这不是这个问题的重点.
当Java 21引入有序集合时,我非常高兴开始使用它们。但后来我很快发现JDK的各个角落似乎都会自然地应用新的排序接口,但它们并没有应用。我找不到对此的任何确认,也找不到任何证据表明未来有计划进一步将排序集合接口的使用扩展到更多 JDK 中。这让我感到惊讶,因为 JDK 的作者通常倾向于保持事物的一致性和完整性。
一个具体的例子是EnumSet。据我所知,没有根本原因EnumSet不能/不应该实施SequencedSet. 难道只是没有人愿意付出努力来实现一种reversed()方法吗EnumSet?或者有什么更严重的问题阻止了它?
enumset ×10
java ×8
enums ×6
collections ×2
bit-fields ×1
eclipse ×1
entity ×1
flags ×1
java-21 ×1
kotlin ×1
mapping ×1
sequencedset ×1
swt ×1