Java 高质量编程建议(笔记3)

来源:互联网 发布:雅思口语书 知乎 编辑:程序博客网 时间:2024/06/03 15:58

       
Ad-18:避免instanceOf非预期结果
    1)instanceOf是一个简单的二元操作符,用来判断一个对象实例是否属于某个类;
    2)直接常量的类型是基本类型,而不是其包装类型, 如果右操作数是包装类型,则编译失败,反之亦然;
    3)instancOf的左操作数如果是null,直接返回false,不关心运算的右操作数是什么类型;
    4)如果对象的类型是是右操作数的子类,则返回成功;
    5)如果左操作数的类型与右操作数的类型不存在父子关系(类型关系树),编译会失败;
    6)右操作数是基本类型(八大基本类型)一定编译不过;
    7)泛型在编译成字节码时,T为Object类型,因此右操作数只要不是基本类型,都能编译通过;
    
Ad-19:断言绝对不是鸡肋
    1)在防御性编程中经常用断言(Assertion)对参数和环境作出判断;
    2)断言使用方法:
        assert <布尔表达式>
        assert <布尔表达式>:<错误信息>
    3)布尔表达式如果为假,抛出AssertionError错误,并附带了错误信息;
    4)assert默认不启用;
    5)assert抛出的异常AssertionError是继承Error的;
    6)assert不能用于以下场景:
        a)对外公才的方法;
        b)在执行的逻辑代码中;
    7)assert使用的三种场景:
        a)在私有方法中使用assert对输入参数做判断;
        b)流程控制中不可能到达的区域;
        c)建立程序探针,例如:函数的两个变量之间的逻辑关系满足某个表达要求,不满足的话,就有异常;
    

Ad-20:不要只替换一个类
    1)一个类中定义的常量(对于final修饰的基本类型和String类型), 编译器会认为是稳定态的(immutable status),所以编译的时候就直接把值编译到字节码中,避免运行期间引用,提升代码执行效率;
    2)对于final修饰的非基本类型, 编译器认为它不是稳定态的,在编译的时候建立引用关系;
    3)对于上述两点, 如果是稳定态的,如果只替换了定义常量的类,那么新的常量不会影响到程序,但是如果不是稳定态的,则新的常量;
   
Ad-21:用偶判断,不用奇判断  
 (i % 2 == 1)? "奇数":"偶数"
    Java中取模的计算方法:
    public static int remainder(int divided, int divisor)
    {
        return divided - divided / divisor * divisor;
    }
   
    因此当 i = -1时,i%2= -1;所以判断是否是偶数,最好是用 i % 2 == 0
   
Ad-22:使用整数类型处理货币
    1)大多数语言中,都支持两种浮点数,分别是float类型(俗称:单精度)和double类型(俗称:双精度),其长度分别是4字节和8字节;
    2)浮点数在计算机中存储都支持IEEE标准,float类型按照IEEE的RS32.24, double类型按照IEEE的RS64.53;
    3)浮点数(注意这里是将浮点数转换成2进制科学计数表示)在计算机中存储分三部分:
        a)符号位(Sign):0表示正数,1表示负数;
        b)指数位(Exponent):用于存储科学计数法中的指数数据,采用移位存储;
        c)尾数位(Mantissa):科学计数法中的基数部分(尾数部分,即小数点后面,因为小数点前面一定是1,没有必要再保存);   
    5)在计算机中,只有0.5的N次方可以准确的表达(前提是精确度有足够的位数)
        例如:0.4 的二进制表示 0.0110, 其中0110循环,无限循环下去;
    6)float类型浮点数占用32Bits,其中符号位S占1Bit,指数位E占8Bits,尾数位占23Bits,其Bit位分布见图;
       double类型浮点数占用64Bits,其中符号位S占1Bit,指数位E占11Bits,尾数位占52Bits,其Bit位分布见图;
      


        关于浮点数,可以参考网上其他文章,下面这篇文章写得很详细;
        http://bbs.chinaunix.net/thread-3746530-1-1.html
        http://blog.csdn.net/masefee/article/details/5272554
    7)在Java中不宜使用浮点数表示货币类型,通常银行或者金融业表示需要表示小数点后(10进制)4位,然后输出的时候经过四舍五入法精确两位(RMB到“分”);
    8)但是由于浮点数的精度问题,通常采用两种方式解决,Java 的BigDicimal或使用整型;
   
   
Ad-23:不要让类型默默转换
    Java的表达式先计算,然后再转换类型,即如果表达是的类型是范围小于赋值的变量类型表示的范围,则表达式先计算,然后再转换类型。
    例如:
    int speed = 30 * 1000 * 1000;
    long dist = speed * 60 * 8;
    计算的结果将出现溢出,原因是speed * 60 * 8 表达式的类型是int类型,计算会溢出,计算完之后,才转换类型;
    修改:
    long dist = 1L * speed * 60 * 8;
   
Ad-24:边界值,防止判断边界值时溢出
    在边界值判断中,经常使用 表达式 与 阈值的大小进行判断。但是表达式可能出现溢出,导致条件表达式判断还是OK的。
    例如:
    一个会员最多拥护2000个优惠商品;某会员当前有800个优惠商品;如果程序判断cur + input < LIMIT;
    如果input出现错误,2147483647,那么将出现异常,但是条件表达式还是返回true的。
   
Ad-25:不要让四舍五入亏了一方
    1)四舍五入在金融和商业运行中经常使用到,但是四舍五入并不是绝对的公平,原因:1~4被舍掉,而5~9则进入,明显入多,舍少;
    2)Java之前,通常使用Math.round来获取制定精度的数值;
    3)银行家舍入法:
        3.1)舍去的位小于5时,则直接舍去;
        3.2)舍去的位大于6时,则直接进位;
        3.3)舍去的位为5时,首先舍去位后面位的数值,如果非0,则进位; 如果舍去位后面位的数值为0,则看舍去位前面,如果为偶数,则舍去,如果为奇数则进位;
    4)在金融和商业软件中,经常使用BigDecimal的setScale方法和RoundingMode来处理各种舍入和进位;
    5)RoundingMode支持7种进位和舍去方法:
        5.1)ROUND_UP: 向远离0方向舍入, 向绝对值最大的方向舍入,只要舍弃位非0即进位;
        5.2)ROUND_DOWN: 向靠近0方向舍入, 向绝对值最小的方向舍入,注意:所有的位都舍弃,不存在进位;
        5.3)ROUND_CEILING:向正无穷方向舍入,与Math.round相同;
        5.4)ROUND_FLOOR:向负无穷方向舍入;
        5.5)HALF_UP: 传统的四舍五入;
        5.6)HALF_DOWN:准确来说是五舍六入;
        5.7)HALF_EVEN:银行家舍入法;

原创粉丝点击