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

来源:互联网 发布:cisco端口类型 编辑:程序博客网 时间:2024/05/22 12:50

Ad-39:使用匿名类的构造函数
Ad-40:匿名的构造函数很特殊
    1)匿名类是指没有名称的类,通常的匿名内是继承自某个类,例如通常创建一个线程如下:
        Thread thr = new Thread(){
            @Override
            public void run()
            {
            //实现自己的业务
            }
        }
    2)内部类没有名称,但是可以通过初始化块进行初始化;
    3)实例分析匿名类
        List list1 = new ArrayList();
        List list2 = new ArrayList(){};
        List list3 = new ArrayList(){{}};
        List list4 = new ArrayList(){{}{}{}};
        3.1)list1 是创建一个ArrayList的对象;
        3.2)list2 是创建一个Arraylist的子类的匿名类,即类似于如下Sub类,只是没有名字而已,而且没有初始化;
            class Sub extends ArrayList
            {
            }
        3.3)list3 创建的也是一个ArrayList的子类的匿名类,类似于如下Sub类,没有名字,有一个初始化块,但是没有做任何初始化;
            class Sub extends ArrayList
            {
                {
                }
            }
        3.4)list4 创建一个ArrayList的子类的匿名类, 类似如下Sub类,没有名字,但是有多个初始化块,但是没有做任何初始化;
            class Sub extends ArrayList
            {
                {
                }
                {
                }
                {
                }
            }
           
           
        3.5)上面list1是ArrayList的实例,list2,list3,list4 是ArrayList的匿名子类的实例,但是它们都属于不同的类;
    4)一般类(带名称的类)的所有构造方法默认都是调用父类的无参构造方法,匿名类没有构造方法,只有构造代码块,也就无所谓的有参数和无参数的构造方法区别,在初始化时直接调用了父类的同参构造方法, 然后调用自己的构造代码块。
   
Ad-41:让多重继承成为现实
    1)Java不支持多重继承,但是可以支持实现多个接口;
    2)内部类可以继承一个与外部类无关的类,保证内部类的独立性,可以利用内部类继承与外部无关的类,来实现多重继承
   
Ad-42:工具类不可实例化
    1)不可实例化的类,首先将类定义加上final修饰,避免类被继承;
    2)不可实例化的类,将构造方法加上private,避免外部实例化类;
    3)不可实例化的类最保险的方法是,构造方法私有化,然后在构造方法内抛出异常;
   
Ad-43:避免对象的浅拷贝
    1)类实现了Cloneable接口就表示类具备拷贝能力,如果覆写了clone方法,那么就具备完全拷贝的能力;
    2)拷贝在内存中进行的,性能比通过new生成对象要快;
    3)浅拷贝(也称影子拷贝,shadow clone),是指对象中引用的对象,拷贝的是其应用,而没有真正复制一个新对象,再引用其新对象;
    4)所有的类都是继承自Object类, 而Object类提供的默认拷贝,但是它是一个浅拷贝的方法,拷贝的规则如下:
        4.1)基本类型(8大基本类型),如果变量的类型是基本类型,则拷贝其值,拷贝之后互不影响;
        4.2)如果变量是对象实例,则拷贝其地址的引用,拷贝的变量和原变量引用的都是同一个对象,就算是private权限的变量,也可以由两个变量访问,也就是说至少可以在两个地方修改变量;
        4.3)String字符串:String也是对象类型,拷贝的时候,也拷贝其地址的引用,但是如果要修改变量的时候,它会从字符串池中重新生成新的字符串,原来的字符串保持不变;
 
Ad-44:推荐使用序列化实例对象的拷贝
    1)通过序列化和反序列化可以实现对象的拷贝;
    2)使用序列化实现对象拷贝需要注意:
        2.1)对象内部的属性都是可序列化,如果内部属性不可序列化,则可能出现无法拷贝;
        2.2)注意方法和属性的修饰符,final、static变量的序列化会被引入到拷贝中来,transient不会被序列化;
    3)疑问:序列化实现对象的拷贝,性能可能会受影响?   
   
Ad-45:覆写equals方法是不要识别不出来自己 
Ad-46:在equals方法要考虑null值
Ad-47:在equals方法中是用getClass()进行类型判断
    1)对象中如果通过String来作为equals的判断依据,要注意字符串前后可能存在空格,特别是当数据经过网络或者从文件中传递之后,可能出现前后有空格的问题,从而导致判断的时候,不能识别出自己;
    2)在equals方法的实现中要考虑null值,避免抛出异常;
    3)通常我们都是用 instanceof进行类型判断,但是 obj instanceof typeclass 中如果obj的真实类型是typeclass的子类,则instanceof 认为是true;
    4)在equals方法中使用getClass()获取对象实例的Class对象,然后用Class对象的equals进行判断,避免instanceof钻空;
   
   
    5)实现equals需要注意以下原则:
        5.1)自反性:一个对象自己与自己肯定是相当的;
        5.2)对称性:对于任何引用x和y,如果x.equals(y)为true,那么y.equals(x)也为true;
        5.3)传递性:对于任何引用x、y、z,如果x.equals(y)为true,而且y.equals(z)也为true,那么x.equals(z)应该为true;
 
Ad-48:覆写equals方法的同时应该覆写hashCode方法
    1)对象的hashCode方法主要用对象存储在Hash容器(HashMap、HashTable、HashSet)中操作比较时用;
    2)以HashMap来说,底层是以数组存储Map的Entry,Entry包含了Key和Value,其关键是下标处理机制:   
        2.1)首先根据Key的hashCode值决定其数组的下标;
        2.2)如果数组的下标位置上已经存在条目,且传入的Key值相等(使用Key对象的equals方法),则不处理;
        2.3)如果数组的下标位置上已经存在条目,但是传入的Key值不相等,则覆盖其Value;
        2.4)如果数组的下标位置上不存在条目,则插入;


    3)对hashCode算法要求:任意输入k,通过算法f(k)将其转换为非可逆的输出,对于两个输入k1和k2,要求k1=k2,则f(k1)=f(k2),但是允许k1!=k2时,f(k1)=f(k2)可以成立;
   
Ad-49:推荐覆写toString方法
    1)Java默认的toString方法打印的内容是:类名+@+hashCode;
    2)方便在大型项目中打印日志定位;
    3)可以方便的控制输出信息,对于不想输出的信息可以隐藏掉;
       

原创粉丝点击