创建自定义 BigDecimal 类型
Creating a custom BigDecimal type
在我的应用程序中,所有 BigDecimal 数字都被缩放为有两位小数。换句话说,每次我在代码中创建一个新的 BigDecimal 时,我也需要使用方法缩放:
BigDecimal x = BigDecimal.ZERO;
x.setScale(2, RoundingMode.HALF_UP);
因此,为了尽量减少工作量,我想创建自定义 BigDecimal 类型,例如:
public class CustomBigDecimal extends BigDecimal {
public CustomBigDecimal(String val) {
super(val);
this.setScale(2, RoundingMode.HALF_UP);
}
}
我知道 this.setScale(2, RoundingMode.HALF_UP);
做不到,但我找不到方法,可以吗?
您可以简单地为自己创建一个方法来创建一个零的 BigDecimal。类似于:
public static BigDecimal scaled(String val) {
BigDecimal x = new BigDecimal(val);
return x.setScale(2, RoundingMode.HALF_UP);
}
将它放在帮助程序 class 中,例如 BigDecimalHelper、BigDecimalFactory 或其他。 :)
编辑:将其稍微更改为 return setScale 的结果,因为 BigDecimal 是不可变的。并进一步回答最初的问题:不,你写的是不可能的,因为对象的状态没有用 setScale() 改变。
例如,您可以存储 MathContext 的单例实例,并将它们用作 BigDecimal 构造函数的参数。
通常你可以这样做:
MathContext context = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal number = new BigDecimal(val, context);
所以,如果你有一个 MathContext 作为单例,你可以这样做:
BigDecimal number = new BigDecimal(val, MathInstanceHolder.getMathContext());
其中 MathInstanceHolder 包含一个 MathContext 实例。
您可以创建一个从 BigDecimal
扩展的 CustomBigDecimal
。但是,由于 BigDecimal
是不可变的,您永远不会从父级 class.
继承状态(例如缩放和舍入模式)
我会选择另一个答案中建议的实用程序 class,或者可能是将每个操作委托给实际 BigDecimal
实例的包装器。这种方法的缺点是您的全新 CustomBigDecimal
不会是 BigDecimal
,因此它们不能互换。
编辑:这种方法的缺点是您必须委托大约 50 个方法。不是世界末日的好IDE,但绝对不是很吸引人...
如果你仍然想让 CustomBigDecimal
继承自 BigDecimal
,你需要使用 decorator 方法:
public class CustomBigDecimal extends BigDecimal {
private final BigDecimal value;
private CustomBigDecimal(BigDecimal value) {
super(value.toPlainString()); // needed to compile,
// useless except for implicit null-check
this.value = value;
}
public CustomBigDecimal(String val) {
this(new BigDecimal(val).setScale(2, RoundingMode.HALF_UP));
}
@Override
public CustomBigDecimal abs() {
return new CustomBigDecimal(this.value.abs());
}
// TODO all other methods
}
只是为了与众不同并利用 Java 8 - 你也可以在问题上使用 lambda:
public static Function<String, BigDecimal> SCALED_BIG_DECIMAL = (val) -> new BigDecimal(val).setScale(2, RoundingMode.HALF_UP);
...
// and this is how you would use it
SCALED_BIG_DECIMAL.apply("20.2343425")
在我的应用程序中,所有 BigDecimal 数字都被缩放为有两位小数。换句话说,每次我在代码中创建一个新的 BigDecimal 时,我也需要使用方法缩放:
BigDecimal x = BigDecimal.ZERO;
x.setScale(2, RoundingMode.HALF_UP);
因此,为了尽量减少工作量,我想创建自定义 BigDecimal 类型,例如:
public class CustomBigDecimal extends BigDecimal {
public CustomBigDecimal(String val) {
super(val);
this.setScale(2, RoundingMode.HALF_UP);
}
}
我知道 this.setScale(2, RoundingMode.HALF_UP);
做不到,但我找不到方法,可以吗?
您可以简单地为自己创建一个方法来创建一个零的 BigDecimal。类似于:
public static BigDecimal scaled(String val) {
BigDecimal x = new BigDecimal(val);
return x.setScale(2, RoundingMode.HALF_UP);
}
将它放在帮助程序 class 中,例如 BigDecimalHelper、BigDecimalFactory 或其他。 :)
编辑:将其稍微更改为 return setScale 的结果,因为 BigDecimal 是不可变的。并进一步回答最初的问题:不,你写的是不可能的,因为对象的状态没有用 setScale() 改变。
例如,您可以存储 MathContext 的单例实例,并将它们用作 BigDecimal 构造函数的参数。
通常你可以这样做:
MathContext context = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal number = new BigDecimal(val, context);
所以,如果你有一个 MathContext 作为单例,你可以这样做:
BigDecimal number = new BigDecimal(val, MathInstanceHolder.getMathContext());
其中 MathInstanceHolder 包含一个 MathContext 实例。
您可以创建一个从 BigDecimal
扩展的 CustomBigDecimal
。但是,由于 BigDecimal
是不可变的,您永远不会从父级 class.
我会选择另一个答案中建议的实用程序 class,或者可能是将每个操作委托给实际 BigDecimal
实例的包装器。这种方法的缺点是您的全新 CustomBigDecimal
不会是 BigDecimal
,因此它们不能互换。
编辑:这种方法的缺点是您必须委托大约 50 个方法。不是世界末日的好IDE,但绝对不是很吸引人...
如果你仍然想让 CustomBigDecimal
继承自 BigDecimal
,你需要使用 decorator 方法:
public class CustomBigDecimal extends BigDecimal {
private final BigDecimal value;
private CustomBigDecimal(BigDecimal value) {
super(value.toPlainString()); // needed to compile,
// useless except for implicit null-check
this.value = value;
}
public CustomBigDecimal(String val) {
this(new BigDecimal(val).setScale(2, RoundingMode.HALF_UP));
}
@Override
public CustomBigDecimal abs() {
return new CustomBigDecimal(this.value.abs());
}
// TODO all other methods
}
只是为了与众不同并利用 Java 8 - 你也可以在问题上使用 lambda:
public static Function<String, BigDecimal> SCALED_BIG_DECIMAL = (val) -> new BigDecimal(val).setScale(2, RoundingMode.HALF_UP);
...
// and this is how you would use it
SCALED_BIG_DECIMAL.apply("20.2343425")