java BigDecimal中的坑们

起初接触这个类就觉得这个类很神奇,各种方法的都不会改变其本身,这也容易引起很多BUG。

比如 BigDecimal.setScale()这个方法,正常理解调用这个方法以后原来的对象的精度就被改变了,但事实并非如此:

    public void test5() {
        BigDecimal decimal = BigDecimal.valueOf(3.333333333);
        System.out.println(decimal);
        decimal.setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println(decimal);
    }

输出结果是  这不是没变化吗?

 

后来发现IDEA的小提示:

他说我把这个方法的返回值忽略了,我看了一下还真是,一般POJO的set方法都是无返回值的,这玩意特立独行有个BigDecimal的返回值。然后我们把代码改成这样:

    public void test5() {
        BigDecimal decimal = BigDecimal.valueOf(3.333333333);
        System.out.println(decimal);
        BigDecimal decimal2 = decimal.setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println(decimal2);
    }

输出结果:果然就可以了。

BigDecimal果然是一个奇葩的类,天真的我以为事情到此就结束了,直到有一天,写的功能又出问题了

 

事情大概是这样的:除了改变了它的精度以外,我还在别的方法里面改了它的值:

    public void test5() {
        BigDecimal decimal = BigDecimal.valueOf(3.333333333);
        System.out.println(decimal);
        BigDecimal decimal2 = decimal.setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println(decimal2);
        change(decimal);
        System.out.println(decimal);
    }

    private void change(BigDecimal bigDecimal) {
        bigDecimal = bigDecimal.multiply(BigDecimal.TEN);
    }

输出结果:这不是又没变吗?没æ³å°å§è¡¨æå [æä¸æåï¼æä¸æå¤ï¼]

 

根据我们以往的概念,调用方法的时候参数为非基本数据类型的都是引用传递,方法里面改了它的值方法外面跟着动,因为它就是同一个实例。但这个BigDecimal好像就是不符合常理。后来查了一下,这个BigDecimal居然是个不可变类。有同学不太理解不可变类是啥?这么说吧,你可以把它理解为它的所有属性就是final的,不可改变。所以你调用它的任何方法都不会改变实例本身,而是创建一个新的对象。就跟String一样。

这样一来都能想的明白了,原来setScale方法也是这个解释。但是为啥我在别的方法里面改这个对象改不了了呢?

我们这样理解一下:

    public void test6() {
        String a = new String("ori");
        BigDecimal b = BigDecimal.TEN;
        System.out.println(a);
        System.out.println(b);
    }

    private void change(String c, BigDecimal d) {
        c = new String("hhh");
        d = BigDecimal.ZERO;
    }

结果:

在调用change方法的时候,b对象的确是传了进去,被形参d指向,这个时候b和d都指向同一个对象,然后我在方法内部把d指向了一个新的对象,但是原来b的指向没变,所以b始终没变。

综上,我们得出如下结论:

1.对不可变类的任何操作都不会改变不可变类本身实例,而是创造一个新的实例(原来不用的实例会在GC时被回收)

2.不可变类作为参数传入方法内,方法内对不可变类的操作不会对方法外部造成影响。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值