Java中容易忽略的错误(其中也引用到了其他博主的内容)(持续更新,查缺补漏)

1.Java中a+=b和a=a+b有什莫区别

在java语言中,a+=b和a=a+b的主要区别是在运算的精度上。类似的有“-= 、 *= 、/= 、%= ”,这里以a+=b 与 a=a+b 举例说明一下。总结一下,在两个变量的数据类型一样时:a+=b 和a=a+b 是没有区别的。但是当两个变量的数据类型不同时,就需要考虑一下数据类型自动转换的问题了。如果进行强制类型转换就会出现精度丢失,需要明确的是“+=”是java中的一个运算符,而不是两个,所以在运算时 会进行自动类型转换。所以在编译时没有报错。
详见:
https://mp.weixin.qq.com/s/K9axe7iQHyqv_7LWXUZp6Q

2.静态变量和实例常量(static修饰的)

静态变量并不是说其就不能改变值,不能改变值的量叫常量。 其拥有的值是可变的 ,而且它会保持最新的值。 说其静态,是因为它不会随着函数的调用和退出而发生变化。即上次调用的时候,如果我们给静态变量赋予某个值的话, 下次函数调用时,这个值保持不变。 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。

对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

final修饰的

是常量,不能被改变。
##3. final和static共同修饰的是全局变量

3.Java中“double计算精度”踩过的keng(2019.7.29.微信公众号:Java知己)

public class Double {
	public static void main(String[] args) {
		System.out.println(0.05+0.01);
		System.out.println(1.0-0.42);
		System.out.println(4.015*100);
		System.out.println(123.3/100);
	}
}

输出:

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

结论:Java中的简单浮点数类型float和double不能够进行精确j运算。会出现精度丢失的问题。适用于科学计算。
原因:(因为计算机只能识别二进制数据,而不能识别其他进制的数据,无论使用何种语言在编译的时候都要转化为二进制的机器码进行识别,而浮点数也需要转化成二进制形式参与运算,在这个过程中就会出现精度的丢失)
解决方法:float和double只能用于科学计算和工程计算。咋商业计算中,用java.math.BigDecimal.
BiigDecimal类由4个方法,这里我们只讲到了两个BigDecimal(double value) // 将double型数据转换成BigDecimal型数据
先通过该方法将double型数据转换成BigDecimal数据,然后就可以正常进行精确计算。等计算完毕后,我们可以对结果做一些处理,比如 对除不尽的结果可以进行四舍五入。最后,再把结果由BigDecimal型数据转换回double型数据。
但是我们如果进行精确计算不能直接用这个方法,而是要涉及到另一种方法:
BigDecimal(String value)能够将String型数据转换成BigDecimal型数据
如果我们要做一个浮点型数据的加法运算,需要先将两个浮点数转为String型数据,然后用 BigDecimal(String value)构造成BigDecimal,之后要在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮 点数。缺点:过程太繁琐
所以最好的办法,就是写一个类,在类中完成这些繁琐的转换过程。这 样,在我们需要进行浮点型数据计算的时候,只要调用这个类就可以了 。目前有一个工具类Arith来完成这个转换操作:

Arith源代码:

import java.math.BigDecimal;

/**
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
* 确的浮点数运算,包括加减乘除和四舍五入。
*/

public class Arith{
    //默认除法运算精度
    private static final int DEF_DIV_SCALE = 10;
    //这个类不能实例化
    private Arith(){
    }

    /**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }
    /**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
     * 小数点以后10位,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1,double v2){
        return div(v1,v2,DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1,double v2,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v,int scale){

        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
};

你可能感兴趣的:(细节错误)