锁定老帖子 主题:是谁破坏了枚举类型?
精华帖 (1) :: 良好帖 (0) :: 新手帖 (14) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2011-05-20
最后修改:2011-05-22
引言: 枚举类型给我们的开发带来了很多的好处,它是个非常典型的一个单例模式,但这样做优越的功能,给我们带来的不全是好处。 当我们开发的接口给别人调用时,往往因为业务需要,添加一个字段类型等等,就也就需要调用端一起更新api包,这里想方设法的去解决这个问题,但这里深深自问题,这是否算是在破坏着这个枚举类型 了呢?
问题: 为了不去经常性的去增加枚举类型的字段,我选择了加方法给出设置值的接口来做个测试,但这样的 测试 出现了一个问题。
示例: 枚举类如下:
/** * @desc 配送物品类型枚举类 */ public enum GoodsType { /** 卡 */ Card("0"), /** 礼品 */ Gift("1"), /** 奖品 */ Prize("2"); public GoodsType setValue(String value) { this.value = value; return this; } GoodsType(String value) { this.value = value; } private String value; public String getValue() { return value; } }
!!! 发现问题: 在这里面出现了一个问题,当这个枚举类在序列化和反序列化之后,对应的值全为默认的参数值了。不管你怎么改变它的值。
以下就做个实验: 服务端: public class Server { public static void main(String[] args) throws IOException, ClassNotFoundException { ServerSocket serversocket = new ServerSocket(1111); System.out.println("端口已启动..."); Socket socket = serversocket.accept(); InputStream is = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); GoodsType goodsType = (GoodsType) ois.readObject(); System.out.println(goodsType.getValue()); System.out.println("测试完成"); } }
客户端: public class Client { public static void main(String[] args) throws UnknownHostException, IOException { Socket socket = new Socket("127.0.0.1", 1111); ObjectOutputStream oos = new ObjectOutputStream(socket .getOutputStream()); GoodsType goodsType = GoodsType.Gift.setValue("22"); System.out .println("before write : goodsType = " + goodsType.getValue()); oos.writeObject(goodsType); System.out.println("after write : goodsType = " + goodsType.getValue()); System.out.println("客户端测试完成"); } }
服务端控制台显示: 端口已启动... 1 服务端测试完成 p.s:服务端接到的值为默认值1.
客户端控制台显示: before write : goodsType = 22 after write : goodsType = 22 客户端测试完成 p.s:客户端接到的值为修改后的值22.
问题原因: 很感谢在这里面,很多“同学”的留言,给的原因和建议都很好,找到了这个问题的原因了。 在传递枚举类型时,其实io中,有专门对它的传输方式,源码如下:
private void writeEnum(Enum en, ObjectStreamClass desc, boolean unshared) throws IOException { bout.writeByte(TC_ENUM); ObjectStreamClass sdesc = desc.getSuperDesc(); writeClassDesc((sdesc.forClass() == Enum.class) ? desc : sdesc, false); handles.assign(unshared ? null : en); writeString(en.name(), false); } 在这里面,枚举传递过去的只是类路径、一个类型名和一个实例名,也就如这里面的Gift这个名字, 而不会把Gift这个值给传递过去,当到传服务器端的时候,服务器端转换过来的也是该枚举类,对应的服务器端Gift类的值而已。
结论: 其实这样的变动想法是在场景应用上而引发了一次思考,这样的做法,其实已经在破坏了枚举类的初衷了。罪魁祸首的人是我 ,但经历这一次的风暴,让我从中对枚举类了解更深刻了。呵呵。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-05-21
enum是声明不变量的,你的 setValue是干什么用的?
|
|
返回顶楼 | |
发表时间:2011-05-21
devworks 写道 enum是声明不变量的,你的 setValue是干什么用的?
为了不去因为要加一种子类型而去再添加一个字段,而是提供可以改变其值,只不过字段里面设好的是默认值而已。 卡下面,又分很多种卡类型,这样的子类型。 |
|
返回顶楼 | |
发表时间:2011-05-21
enum序列化的时候,具体值没有序列化?
|
|
返回顶楼 | |
发表时间:2011-05-22
sammor 写道 devworks 写道 enum是声明不变量的,你的 setValue是干什么用的?
为了不去因为要加一种子类型而去再添加一个字段,而是提供可以改变其值,只不过字段里面设好的是默认值而已。 卡下面,又分很多种卡类型,这样的子类型。 按你这么说, 就不是不变量了 应该是像性别这种, 值(几乎)不会改变的常量, 才用枚举的 |
|
返回顶楼 | |
发表时间:2011-05-22
zjykzk 写道 enum序列化的时候,具体值没有序列化?
对于setValue进去的值,序列化过去就没有了,恢复到默认值去了。 |
|
返回顶楼 | |
发表时间:2011-05-22
lowzoom 写道 sammor 写道 devworks 写道 enum是声明不变量的,你的 setValue是干什么用的?
为了不去因为要加一种子类型而去再添加一个字段,而是提供可以改变其值,只不过字段里面设好的是默认值而已。 卡下面,又分很多种卡类型,这样的子类型。 按你这么说, 就不是不变量了 应该是像性别这种, 值(几乎)不会改变的常量, 才用枚举的 是的,你说的没错,这就是于选择枚举与不选择枚举的问题了。 当我把这个枚举提使到一个jar包里面当api提供给别人使用,往往业务的需求而需要改变到,如“卡”类型下面又开始要份多种卡类型,这时,每一次的增加,我都需要往这个枚举类里面加一个变量,包需要更新,也需要告知调用方,把包更新一下,这样的工作量太大了。 与其如此,倒不如直接写个类,里面有一个Int字段。呵呵。 不知道还有没有更好的办法呢? |
|
返回顶楼 | |
发表时间:2011-05-22
你这标题应该改成 是谁设计了这种垃圾代码
|
|
返回顶楼 | |
发表时间:2011-05-22
qianhd 写道 你这标题应该改成 是谁设计了这种垃圾代码
哈哈,是我故意这么做的,不是为了设计,只是一个实验。 |
|
返回顶楼 | |
发表时间:2011-05-22
你的代码设计有问题,既然用了枚举为什么还有把他的状态value改变!
|
|
返回顶楼 | |