一、通過返回數組(或集合)實現
@Test
public void test1(){
int a = 10,b =7;
int[] compute = compute(a,b);
System.out.println("兩數之和:"+compute[0]);
System.out.println("兩數之差:"+compute[1]);
}
private int[] compute(int a,int b){
return new int[]{a+b,a-b};
}
- 顯然這有致命的缺點,你無法通過下標直觀的對應[0]是什么含義,[1]是什么含義,特別是別人閱讀你的代碼可能會有些許的壓力。可維護性非常差。
二、通過參數列表帶回返回值
- 同樣一種比較常用的方式,參考代碼如下
@Test
public void test2(){
int a = 10, b = 7;
IntBox aBox = new IntBox(a);
IntBox bBox = new IntBox(b);
compute2(aBox,bBox);
System.out.println("兩數之和:" + aBox);
System.out.println("兩數之差:" + bBox);
}
private void compute2(IntBox a,IntBox b){
int diff = a.value - b.value;
int sum = a.value + b.value;
a.value = sum;
b.value = diff;
}
private class IntBox{
private int value;
public IntBox(int value){
this.value = value;
}
@Override
public String toString(){
return String.valueOf(value);
}
}
缺點
- 基本類型不支持,必須封裝成對象,比如上述代碼封裝了
IntBox
,造成代碼量冗長。 - 反代碼閱讀直覺,可讀性極差。在別人閱讀你的代碼時,看到方法調用,一般認為傳遞了xx參數,獲取到xx返回值,而不是參數都甚至被改變,這極大的增加了維護和理解成本,他為了了解參數被發生什么改變,甚至必須深入方法內部邏輯。
>
>
此方法由於過於反直覺、代碼量冗長,可讀性、可維護性極差,是充滿妥協的解決方案。但由於是最簡單的方法,所以在新手中不少見,我個人建議不到萬萬不得已,別使用。
三、通過map實現
比較容易想到的另一種方案,多返回值通過key-value形式返回,示例如下:
@Test
public void test3(){
int a = 10,b =7;
Map<String, Integer> resMap = compute3(a,b);
System.out.println("兩數之和:" + resMap.get("sum"));
System.out.println("兩數之差:" + resMap.get("diff"));
}
private Map<String,Integer> compute3(int a,int b){
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("diff",a-b);
hashMap.put("sum",a+b);
return hashMap;
}
- 此方式和數組返回值有相似的地方,可以當做前者的升級版,但map的key是可讀的,而數組的下標是沒有可讀性的。
- 雖然消除了“數組返回值”時下標不可讀性的理解困難問題,但引入的硬編碼魔法值已經容易造成維護困難,比如后期可能忘記key的值是sum還是summation,甚至單詞拼錯都會把bug引入打運行時。這是動態語言常見的問題,在java身上不應該出現。
四、使用枚舉作為key消除硬編碼
hashMap作為返回值時,最大的缺點就是key的值是string魔法值,消除魔法值常見的辦法就是枚舉。因此考慮枚舉替代String作為key,代碼如下
@Test
public void test3(){
int a = 10,b =7;
Map<ResType, Integer> resMap = compute3(a,b);
System.out.println("兩數之和:" + resMap.get(ResType.SUM));
System.out.println("兩數之差:" + resMap.get(ResType.DIFF));
}
private Map<ResType,Integer> compute3(int a,int b){
HashMap<ResType, Integer> hashMap = new HashMap<>();
hashMap.put(ResType.DIFF,a-b);
hashMap.put(ResType.SUM,a+b);
return hashMap;
}
enum ResType{
SUM,
DIFF
}
emmm,比上述好得多了,但是還是有優化空間。
- 在方法中必須顯式創建一個hashMap比較麻煩。
- 第9行map的泛型是可以不指定的,如果遇到不規范的隊友,依舊存在硬編碼問題。
- 必須多定義一個枚舉,一定程度上增加代碼量
最終方案:基於enumMap的自定義返回值
創建自定義返回值MutiResult.java代碼如下:
public class MutiResult<K extends Enum<K>,V>{
private Map<K, V> resultMap;
private MutiResult(Map<K, V> resultMap){
this.resultMap = resultMap;
}
/**
* 獲取返回值
*
* @param key
* @return
*/
public V get(K key){
return resultMap.get(key);
}
public static <K extends Enum<K>,V> Builder<K, V> build(){
return new Builder<>();
}
/**
* @param keyClass key的類型
* @param valueClass value類型
* @return 建造者對象
*/
public static <K extends Enum<K>,V> Builder<K, V> build(Class<K> keyClass,Class<V> valueClass){
return new Builder<>();
}
/**
* 建造者
*
* @param <K>
* @param <V>
*/
public static final class Builder<K extends Enum<K>,V>{
private Map<K, V> resultMap;
Builder(Map<K, V> resultMap){
this.resultMap = resultMap;
}
Builder(){
this(new ConcurrentHashMap<>());
}
/**
* 生成目標類
*
* @return
*/
public MutiResult<K, V> build(){
return new MutiResult<>(resultMap);
}
/**
* @param key
* @param value
* @return
* @throws IllegalArgumentException 多次添加同一個key拋出此異常
*/
public Builder<K, V> add(K key,V value){
if(resultMap.get(key) != null){
throw new IllegalArgumentException("重復添加key:" + key);
}
resultMap.put(key,value);
return this;
}
}
使用方法:
enum ResType{
SUM,
DIFF
}
@Test
public void test4(){
int a = 10,b =7;
MutiResult<ResType, Integer> resMap = compute4(a,b);
System.out.println("兩數之和:" + resMap.get(ResType.SUM));
System.out.println("兩數之差:" + resMap.get(ResType.DIFF));
}
private MutiResult<ResType, Integer> compute4(int a,int b){
return MutiResult.build(ResType.class,Integer.class)
.add(ResType.SUM,a+b)
.add(ResType.DIFF,a-b)
.build();
}