用泛型消灭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。