我有个一个这样的需要,已知有A、B、C三相位,其中0代表B,1表示A,2表示C,其他参数输出错误。现在有一个入参,输入一个数字,要求返回对应的相位得到String类型。比如,入参是0,那么我需要得到 A相 这样的输出答案。
笔者之前确实没有用过Enum,那么首先,在没有Enum的情况下,我或许会尝试这样去写代码:
public class Phase { private static String getPhaseStr(int tag) { if (tag == 0) return "B"; if (tag == 1) return "A"; if (tag == 2) return "C"; return "错误"; } public static void main(String[] args) { int input = 0; System.out.println(getPhaseStr(input)); } }
这样确实是完成我的需求了。那么现在,我又有了一个需求,入参是一个String类型的,可能是"A""B""C"要求得出其对应的数字,其他输入输出-1,。比如,入参是“A”,出参就应该是1。
ok照着上面代码的思路,我可以能会这样去修改代码:
public class Phase { private static String getPhaseStr(int tag) { if (tag == 0) return "B相"; if (tag == 1) return "A相"; if (tag == 2) return "C相"; return "错误"; } private static int getPhaseTag(String phase) { if ("A相".equalsIgnoreCase(phase)) return 1; if ("B相".equalsIgnoreCase(phase)) return 0; if ("C相".equalsIgnoreCase(phase)) return 2; return -1; } public static void main(String[] args) { // int input = 0; // System.out.println(getPhaseStr(input)); String phase = "A相"; System.out.println(getPhaseTag(phase)); } }
好吧,代码开始变得丑陋了,不过anyway,也完成了我的需求。
好了,那么现在我又一个新的需求,某某人告诉我,一开始在定义ABC的时候定义错了,A代表0,B代表1,C代表2。好吧,开始头大了,那么我现在或许要考虑我是否需要重新写下代码,万一,到时候某某又告诉我需要加D呢?
public class Phase2 { private static Map<Integer, String> map = new HashMap<Integer, String>(); static { map.put(0, "A相"); map.put(1, "B相"); map.put(2, "C相"); } private static String getPhaseStr(int tag) { String phase=map.get(tag); phase==null?"错误":phase; } private static int getPhaseTag(String phase) { for (Map.Entry<Integer, String> e : map.entrySet()) { if (phase.equalsIgnoreCase(e.getValue())) return e.getKey(); } return -1; } }
确实满足了我的需求,而且扩展性也变得似乎还不错。可是我之前在很多框架的源码里面有见到Enum,总觉得是个高级货,所以我也来尝试用一下:
public enum Phase3 { A(0, "A相"), B(1, "B相"), C(2, "C相"), ERROR(-1, "错误"); private int tag; private String info; private Phase3(int tag, String info) { this.tag = tag; this.info = info; } public int getTag() { return tag; } public void setTag(int tag) { this.tag = tag; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public static String getPhaseStr(int tag) { for (Phase3 p : Phase3.values()) { if (p.getTag() == tag) return p.getInfo(); } return ERROR.getInfo(); } public static int getPhaseTag(String s) { for (Phase3 p : Phase3.values()) { if (s.equalsIgnoreCase(p.getInfo())) return p.getTag(); } return ERROR.getTag(); } public static void main(String[] args) { int input = 0; System.out.println(Phase3.getPhaseStr(input)); String phase = "A相"; System.out.println(Phase3.getPhaseTag(phase)); } }
为了找到答案,笔者特意去学习了下《thinging in java》,或许是我水平不够,确实有看到一堆例子,但是,实际中,我似乎从来没有看到过谁这么使用过,而且其中有个什么"使用分发",请问分发到底是什么意思,反正这一段我是看得云里雾里的,而且并没有发现这样使用的好处。
但是有一点,我通过javap去反编译了一下Phase3.class得到以下结果:
public final class myenum.test.Phase3 extends java.lang.Enum<myenum.test.Phase3> {
public static final myenum.test.Phase3 A;
public static final myenum.test.Phase3 B;
public static final myenum.test.Phase3 C;
public static final myenum.test.Phase3 ERROR;
static {};
public int getTag();
public void setTag(int);
public java.lang.String getInfo();
public void setInfo(java.lang.String);
public static java.lang.String getPhaseStr(int);
public static int getPhaseTag(java.lang.String);
public static void main(java.lang.String[]);
public static myenum.test.Phase3[] values();
public static myenum.test.Phase3 valueOf(java.lang.String);
}
1.enum里面的最终被编译成了:public static final myenum.test.Phase3 A; 每一个枚举里面的类型都被编译成一个Phase3的对象,而且extends了java.lang.Enum。这就意味着Phase3里面的所有的方法都可以使用。结论就是,把enum里面的每个类型都看作一个对象吧,它可以实现接口,但是不能extend。
2.通过学习,Phase3还可以写成这样:
public enum Phase4 {
A(0) {
@Override
public String getInfo() {
return "A相";
}
},
B(1) {
@Override
public String getInfo() {
return "B相";
}
},
C(2) {
@Override
public String getInfo() {
return "C相";
}
},
ERROR(-1) {
@Override
public String getInfo() {
return "错误";
}
};
private int tag;
private Phase4(int tag) {
this.tag = tag;
}
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public abstract String getInfo();
public static String getPhaseStr(int tag) {
for (Phase4 p : Phase4.values()) {
if (p.getTag() == tag)
return p.getInfo();
}
return ERROR.getInfo();
}
public static int getPhaseTag(String s) {
for (Phase4 p : Phase4.values()) {
if (s.equalsIgnoreCase(p.getInfo()))
return p.getTag();
}
return ERROR.getTag();
}
public static void main(String[] args) {
int input = 0;
System.out.println(Phase4.getPhaseStr(input));
String phase = "A相";
System.out.println(Phase4.getPhaseTag(phase));
}
}
这段代码的精髓在于这个abstract,可见枚举的对象还可以有自己的方法。
3.在操作枚举类型的时候,可能会用到EnumMap和EnumSet
4.《Thinking in Java》中Enum的那些Enum看不懂的地方,直接忽略吧。使用Enum最初的功能就好。
5.使用Enum并不能使代码的效率更高,但是他能让代码的更加的优雅帅气。接下来在日常的代码中尽量多用吧,或许多用会有不同的体会。
另外在书中有看到几个有意思的东西:
1.静态导入包 import static ****;
2.System.getenv("")可以获取环境变量System.getProperties(“java.version”)可以获取java版本
3.书中有提到用Enum实现职责链(Chain of Responsibility),这个是不是很像mina的handler,一层一层的提交。