zoukankan      html  css  js  c++  java
  • 《编写高质量代码—改善java程序的151个建议》知识整理一

    1、用偶判断,不用奇判断

         案例:在代码i%2==1?"奇数":"偶数" (java中的求余算法相当于:divided-divided/divisor*divisor)中,当被除数i为-1时,结果是偶数,判断失误,所以该程序应改为:i%2==0?"偶数":"奇数"

    2、不要让类型默默转化

        案例:代码long d=lg*60*8,当整型的lg参数和另外两个参数相乘超出整型边界的时候就会变成负数,在转换为long型,结果还是负值

                    所以代码需要改为:long d=lg*60*8*1l;

    3、在接口中不要存在实现代码

    public class Client {
        public static void main(String[] args) {
            //调用接口的实现
            B.s.doSomething();
        }
    }
    
     interface B {
         public static final S s=new S(){
             public void doSomething(){
                 System.out.println("我在接口中实现了");
             }
         };
    }
    
    interface S {
        public void doSomething();
    }

    虽然成功打印出了结果。但是如果把实现代码写到接口中,那接口就绑定了可能变化的因素,这就会导致实现不再稳定和可靠,是随时都可能被抛弃、呗更改、被重构的。所以接口中虽然可以有实现,但应该避免使用。

    4、静态变量一定要先声明后赋值

    代码:

    public class demo2 {
        
        static{
            i=100;
        }
        public static int i=1;
        public static void main(String[] args) {
            System.out.println(i);
        }
        
    }
    public class demo2 {
        public static int i=1;
        static{
            i=100;
        }
        //public static int i=1;
        public static void main(String[] args) {
            System.out.println(i);
        }
        
    }

           两段代码的输出结果分别为:1和100,两段代码都能编译,都有结果,值却不一样,这是什么原因呢?我们知道静态变量是类加载时被分配到数据区(Date Area)的,它在内存中只有一个拷贝,它以后的所有操作都是只改变值而不改变地址,而jvm是先声明再赋值,例如:int i=100;等价于int i;//分配地址  i=100//赋值,所以在类初始化的时候,jvm会查找类中的所有静态声明进行加载,然后分配空间。所以向上面这种情况,只是完成了地址空间的分配,而没有赋值,之后jvm就会按照先后顺序来进行复制,所以第二段代码到最后输出的结果为1也就不足为奇了。

    5、不要覆写(Override)静态方法,可以隐藏

        代码:

    public class Baseextend {
        public static void doSomething(){
            System.out.println("我是父类静态方法");
        }
        public void doAnything(){
            System.out.println("我是父类非静态方法");
        }
    }
    
    public class Subextend extends Baseextend{
    
        public static void doSomething(){
            System.out.println("我是子类静态方法");
        }
        public void doAnything(){
            System.out.println("我是子类非静态方法");
        }
    }
    
    public class Extendtext {
        @SuppressWarnings("static-access")
        public static void main(String[] args) {
              Baseextend base=new Subextend();
              base.doSomething();
              base.doAnything();
              
    
        }
    }

          上面的输出结果为:我是父类静态方法        我是子类非静态方法

          分析原因:我们知道一个实例对象有两个类型:表面类型(Apparent Type)和实际类型(Actual Type),表面类型是声明时的类型,实际类型是对象产生时的类型。比如例子base的表面类型是Baseextend,实际类型是Subextend。对于非静态方法,它是根据对象的实际类型来执行的,对于静态方法,如果采用类实例(对象)的方法来访问,jvm则会通过对象的表面类型来访问对应的静态方法,所以出现上面的结果也就不足为奇了。

    世上无难事,只怕有心人
  • 相关阅读:
    chroot 与 jail
    3-07. 求前缀表达式的值(25) (ZJU_PAT数学)
    一种监控全部账户登陆及操作命令的方法
    怎样设计接口?
    UVA10869
    网络直播电视之M3U8解析篇 (下)
    LCD显示--Ht1621b芯片显示屏驱动
    混淆
    android 调试
    eclipse+webservice开发实例
  • 原文地址:https://www.cnblogs.com/shewu/p/5412884.html
Copyright © 2011-2022 走看看