Tan*_*ir1 2 java reflection enums
在Java中声明来自多个库的常量分组有哪些选择?
例如,我有一个网络消息协议.该协议具有一些标准消息,并允许创建自定义消息.每条消息都有一个唯一的ID号.我真的想将所有这些唯一ID组合到我的应用程序中的枚举中.就像是...
public enum MessageType
{
//Standard messages in one library
FooMsg(1),
BarMsg(2),
//Custom messages in another library
MyCustomMessage(100),
MyOthercustomMessage(101);
private long msgNumber;
public long getMessageNumber(long msgNumber) { return msgNumber;}
public static MessageType fromMessageNumber(long messageNumber)
{
//Reverse lookup code here...
}
//Few more utilities that don't matter for this question
private MessageType(long msgNumber)
{
this.msgNumber = msgNumber;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我可以创建一个消息类型的通用方法.
public void doStuff(MessageType msgType, MyMessageObject data)
{
switch(msgType)
{
case FooMsg: //Do stuff
break;
//Other stuff
}
}
Run Code Online (Sandbox Code Playgroud)
但是,枚举要求我在编译时知道所有消息类型,但消息分布在多个库中.其中一些库是可选的加载,因此如果它们未加载,我不想将它们包含在枚举中.
有没有办法在运行时定义一个"常量集合",其功能类似于枚举?
你不能用a来做enum,但是有什么理由说简单Map不能满足你的目的吗?或者,既然你有一些其他的实用方法,一个由Map支持的类?您只能为已加载的库添加这些消息,并且如果应用程序的加载阶段和运行阶段之间有明确的描述,您甚至可以使用构建器模式并将Map冻结为不可变映射,以便一次应用程序正在运行,无法对消息进行进一步更改.
(这可以使用Collections.unmodifiableMap()Guava中的任何一个或一个不可变映射类型来完成.)
我不清楚的一件事是,您是否可以保证不同库使用的消息不会发生冲突.这可能是一个问题.
例如:
import java.util.HashMap;
import java.util.Map;
public class MessageType {
private final static Map<Long, MessageType> messageTypes = new HashMap<>();
// it isn't clear how the libraries would provide information on
// the message types they support; suppose that each library has a
// MessageInfo that implements Map<Long, String> with all its types:
public static void loadLibrary(MessageInfo messageInfo) {
// populate the map with each message type it supports
for (Map.Entry<Long, String> entry : messageInfo.entrySet()) {
MessageType messageType =
new MessageType(entry.getKey(), entry.getValue());
messageTypes.put(entry.getKey(), messageType);
}
}
// A MessageType has a name and a number
private final long number;
private final String name;
private MessageType(long number, String name) {
this.number = number;
this.name = name;
}
public long getMessageNumber() {
return number;
}
public String getMessageName() {
return name;
}
public static MessageType fromMessageNumber(long number) {
if (!messageTypes.containsKey(number)) {
throw new IllegalArgumentException("Unknown message: " + number);
}
return messageTypes.get(number);
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以添加检查,以确保没有定义重复的消息类型,有消息类型null名称或号码不被创建,并添加hashCode(),equals(Object)和toString()那个在名称和数量取决于方法.例如,
@Override
public String toString() {
return "message:" + name + "<" + number + ">";
}
Run Code Online (Sandbox Code Playgroud)
或者您希望显示消息以进行调试.请注意,因为只为每种消息类型创建了一个MessageType对象,所以将它们与它们进行比较应该是安全的==,尽管您没有获得从Java enum类型获得的强大保护.(仍然可以MessageType通过反射创建重复的对象,或者,如果你Serializable通过序列化和反序列化来创建重复的对象.)(这种方法,其中每个不同的值只创建一个实例,称为Flyweight设计模式,你可能知道.)
| 归档时间: |
|
| 查看次数: |
43 次 |
| 最近记录: |