用泛型消灭if – else if - else
消灭if-else if - else的方法多种多样,其中看似远在天边的泛型是一种方法。
这种方法多用在每个分支看上去非常相近,甚至有点眼花缭乱的情况。比如:
public class FormulaValueOld { public enum Types {Integer, BigInteger, Float } //... 10 types public Types type; public Integer integerValue; public BigInteger bigIntegerValue; public Float floatValue; //....10 types. public void setValue(Object value) { if (value instanceof Integer) { this.type = Types.Integer; this.integerValue = (Integer)value; } else if (value instanceof BigInteger) { this.type = Types.BigInteger; this.bigIntegerValue = (BigInteger)value; } else if (value instanceof Float) { this.type = Types.Float; this.floatValue = (Float)value; } //... 10 branches. } public Integer integerValue() { return integerValue; } public Object getValue() { if (type.equals(Types.Integer)) { return this.integerValue; } else if (type.equals(Types.BigInteger)) { return this.bigIntegerValue; } else if (type.equals(Types.Float)) { return this.floatValue; } else { return null; } } //... 10 types. }
这个简单的例子来自2018年的一个Java项目,上面的类是一种“公式值”,希望能在一个类中存储10个不同类型的数值。
在这个例子中每个分支只有1~2行代码,而复杂的例子中可以达到10多行,但都具备一个特征:那就是每个分支结构非常类似。
很多人的第一直觉是可以存储在Object类型的公共值中(实际上在这个项目的其他代码中大量存在),但在getValue时,仍然不能解决需要用type来转换为实际类型的分支。
这种分支几乎完全相同的情况,应该使用泛型解决。
具体实现如下(实际代码中并不需要getValue方法,仅为示例):
public class FormulaValue<T> { protected T value; public void setValue(T value) { this.value = value; } public T getValue() { return this.value; }
泛型的官方应用场景可以理解为:行为相同,类型不同。
尽管这是一个很容易理解的概念,然而在很多代码中极少发现除了标准库(List,Map等)之外项目自己创建的泛型类、泛型方法;反而是长相相似的switch case, if-else if-else一大堆。
这时候可以换一个表述或许更好:
泛型的应用场景可以理解为:替代行为相同,类型不同的switch case, if-else if-else。