在开发游戏的过程中遇到了成就统计溢出的问题,情况是统计获取金币的时候,对于一个玩家来说获取金币是无上限的,但是在程序里面使用的是Integer类型,所以会存在上限,一旦超过Integer上限,就会报错.
public void addNum(int num){
totalNum += num;
}
这样的代码很明显到了后期,玩家金币数目获取过多就会报错.
我采用了比较折中的办法:
public boolean addNum(int num){
if((long)totalNum + (long)num > Integer.MAX_VALUE){
return false;
}
totalNum += num;
return true;
}
虽然这样能够完成需求,单仍有很多问题,比如传入值小于0,线程安全等等问题.后来经过前辈提点,又修改了一个版本:
public int addNum(int vi) {
synchronized (this) {//同步
if (vi > 0) {
if (Integer.MAX_VALUE - vi < value) {
value = Integer.MAX_VALUE;
} else {
value += vi;
}
} else if (vi < 0) {
if (Integer.MIN_VALUE - vi > value) {
value = Integer.MIN_VALUE;
} else {
value += vi;
}
}
value = value < 0 ? 0 : value;
return value;
}
}
这样,就可以完成成就的统计并且不会溢出.但仍然有问题,关于经验使用的是Long计数,所以我需要在写一个传参为Long的方法,并不利于拓展,所以我修订了一下.
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 修订版本
*
* @author JasonHung
* @param <T>
*/
public class AmotNumber<T extends Number> implements Serializable, Cloneable {
private AmotNumber() throws Exception {
throw new Exception("不提供无参的构造方法");
}
private volatile T t;//某一类统计的具体数目
private String typeName;//传入参数的具体类型,即泛型的具体类型
public AmotNumber(T value) throws Exception {
if (typeName == null || "".equals(typeName)) {
getTrueType(value);
switch (typeName) {
case "java.lang.Integer":
Integer vi = (Integer) value;
Integer i = t == null ? 0 : (Integer) t;
i += vi;
t = (T) i;
break;
case "java.lang.Double":
Double vd = (Double) value;
Double d = t == null ? 0 : (Double) t;
d += vd;
t = (T) d;
break;
case "java.lang.Long":
Long vl = (Long) value;
Long l = t == null ? 0 : (Long) t;
l += vl;
t = (T) l;
break;
case "java.lang.Float":
Float vf = (Float) value;
Float f = t == null ? 0 : (Float) t;
f += vf;
t = (T) f;
break;
default:
throw new Exception("数据类型错误");
}
}
}
/**
*
* @param vi 传入的变值
* @return
* @throws Exception
*/
public T addNum(T vi) throws Exception {
synchronized (this) {//同步
switch (typeName) {
case "java.lang.Integer":
Integer i = t == null ? 0 : (Integer) t;
Integer v = (Integer) vi;
if (v > 0) {
if (Integer.MAX_VALUE - v < i) {
i = Integer.MAX_VALUE;
} else {
i += v;
}
} else if (v < 0) {
if (Integer.MIN_VALUE - v > i) {
i = Integer.MIN_VALUE;
} else {
i += v;
}
}
i = i < 0 ? 0 : i;
t = (T) i;
return t;
case "java.lang.Long":
Long l = t == null ? 0 : (Long) t;
Long vl = (Long) vi;
if (vl > 0) {
if (Long.MAX_VALUE - vl < l) {
l = Long.MAX_VALUE;
} else {
l += vl;
}
} else if (vl < 0) {
if (Long.MIN_VALUE - vl > l) {
l = Long.MIN_VALUE;
} else {
l += vl;
}
}
l = l < 0 ? 0 : l;
t = (T) l;
return t;
case "java.lang.Double":
Double d = t == null ? 0 : (Double) t;
Double vd = (Double) vi;
if (vd > 0) {
if (Double.MAX_VALUE - vd < d) {
d = Double.MAX_VALUE;
} else {
d += vd;
}
} else if (vd < 0) {
if (Double.MIN_VALUE - vd > d) {
d = Double.MIN_VALUE;
} else {
d += vd;
}
}
d = d < 0 ? 0 : d;
t = (T) d;
return t;
case "java.lang.Float":
Float f = t == null ? 0 : (Float) t;
Float vf = (Float) vi;
if (vf > 0) {
if (Float.MAX_VALUE - vf < f) {
f = Float.MAX_VALUE;
} else {
f += vf;
}
} else if (vf < 0) {
if (Float.MIN_VALUE - vf > f) {
f = Float.MIN_VALUE;
} else {
f += vf;
}
}
f = f < 0 ? 0 : f;
t = (T) f;
return t;
default:
throw new Exception("数据类型错误");
}
}
}
private void getTrueType(T value) {
typeName = value.getClass().getTypeName();
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public static void main(String[] args) throws Exception {
AmotNumber<Double> a = new AmotNumber<>(1.0);
a.addNum(2.0);
Map<String, AmotNumber> as = new HashMap<>();
as.put("d", a);
AmotNumber<Double> get = as.get("d");
get.addNum(100.0);
get.addNum(10000.0);
Number t1 = get.getT();
System.out.println("i=" + t1);
}
}