如何修复适配Number子类的Java Generics栈的运算及返回值问题
Java泛型实现Number子类栈的问题说明与修复
现存问题
- Number类的运算限制:Number是所有数值包装类的抽象父类,本身没有定义加减乘除的运算方法,Java也不支持对两个Number实例直接做算术运算,必须先转为对应的基本数据类型才能计算,这是最开始直接用Number做类型时没法做加减的核心原因。
- addFirstTwo方法语法错误:
- Integer分支的
summe变量仅声明未赋值,summe =后为空,属于语法不合法 summe变量仅在各if分支内部声明,方法末尾访问summe时会报变量未定义的错误- 算术运算得到的是基本数据类型(如double、long),直接赋值给泛型类型
N会报类型不匹配错误,需要先转为对应的包装类再强转为N - 缺少非Integer/Double/Float/Long的Number子类处理逻辑(比如Short、BigDecimal等),如果栈里存储这些类型,方法会直接走到末尾,访问未定义的summe变量
- Integer分支的
- 泛型返回值赋值问题:
pop()方法返回的是N extends Number类型,属于引用类型,如果要赋值给基本类型变量,需要主动调用对应的拆箱方法,比如赋值给int就调用.intValue(),赋值给double就调用.doubleValue(),不能直接自动拆箱,因为编译器无法确定具体的Number子类类型,所以会提示类型不匹配。
修复后的参考代码
public class StackArrayList<N extends Number> { private ArrayList<N> stackList = new ArrayList<>(); public void push (N value) { if(value == null) { System.out.println("value null not allowed"); return; } stackList.add(0,value); } public N pop() { if(stackList.isEmpty()){ return null; } N popInt = stackList.get(0); stackList.remove(0); return popInt; } public N addFirstTwo() { if(stackList.size() == 1) { return stackList.get(0); } if (stackList.size() == 0) { return null; } N summe = null; // 先取出两个元素,避免多次pop顺序出错 N first = pop(); N second = pop(); if(first instanceof Integer) { int sum = first.intValue() + second.intValue(); summe = (N) Integer.valueOf(sum); }else if(first instanceof Double){ double sum = first.doubleValue() + second.doubleValue(); summe = (N) Double.valueOf(sum); }else if(first instanceof Float){ float sum = first.floatValue() + second.floatValue(); summe = (N) Float.valueOf(sum); }else if(first instanceof Long){ long sum = first.longValue() + second.longValue(); summe = (N) Long.valueOf(sum); }else if(first instanceof Short){ short sum = (short) (first.shortValue() + second.shortValue()); summe = (N) Short.valueOf(sum); } // 其他Number子类可自行扩展处理逻辑 if(summe != null){ push(summe); } return summe; } }
使用注意事项
- 把pop的返回值赋值给基本类型变量,写法参考:
int val = stack.pop().intValue();,如果确定栈存储的是Integer类型,也可以写int val = (Integer) stack.pop();利用自动拆箱 - 如果需要支持BigDecimal等其他Number子类,在addFirstTwo的分支中补充对应处理逻辑即可
内容的提问来源于stack exchange,提问作者David Rumpf
相关产品推荐
相关产品推荐

