Thinking in Java 笔记(二)

来源:互联网 发布:js模仿select 编辑:程序博客网 时间:2024/05/22 14:46
一、方法重载 overload

1、 构造方法的重载
    1)如果类中没有默认的构造方法,编译器会自动添加;如果存在了构造方法,编译器将不再添加默认构造方法,因为它会认为你已经很明白如何构造此类了。
    2)构造方法的名字都是类名,没有返回值。
    3)在构造方法中可以通过this关键字来调用其他的构造方法,如this("hello"); 必须将这一句话写在最前面,而且只能在构造函数中这么使用。因此一个构造函数
        当中只能调用一次this(xxx); 因为写第二句的时候已经不满足“this(xxx) 只能出现在构造方法的最前面”这一条件 了
2、 区分方法重载
    1) 每个重载的方法都必须有一个独一无二的参数类型列表,这是唯一的区分方法。返回值类型的不同无法区分两个重载的方法。
    如 void  f(int i)  和 int f(int i), 当系统调用时,不返回任何值时,就会产生歧义,无法知晓调用的方法,因此只能通过参数列表区分两个重载的方法
    2) 可变的参数列表
        void f(Object[] args); //参数的数量和类型都是可变的 , 也可以写成 void f(Object ... args);
        通过代码来更深体会一下:
public class VariousParams{static void func(float f, Character ... chars){System.out.println("first float"+f);for(Character ch : chars){System.out.print(ch+"\t");}}/*static void func(Character ... chars){//如果直接使用这个,因为自动包装机制,会将第一个字符转换成float,也可以是char,有歧义System.out.println("second ");for(Character ch : chars){System.out.print(ch+"\t");}}*/static void func(int i,Character ... chars){//改进后的方法。添加一个非可变参数System.out.println("second int"+i);for(Character ch : chars){System.out.print(ch+"\t");}}public static void main(String args[]){func('a','b','c');//如果不引入非可变参数,这会引起歧义,因为Java的自动包装机制System.out.println();//优先选择可以直接匹配的,再考虑强制转换func(1.0f,'a','b','c');}}


二、垃圾回收 Garbage Collection
    1、基本原则
        对象可能不被垃圾回收;垃圾回收不等于析构;垃圾回收只与内存有关
    2、finalize
        程序员可以自己干预某些对象的垃圾回收,一般是调用了JNI的方法,使用其他语言分配的内存,垃圾回收机制无法操控这些,如果不释放,易内存泄露。
        使用方式举例:
   
 public class SystemTest{public static void main(String args[]){Book b=new Book("1");b.checkout();    //正常终止new Book("2");    //没有正常结束的对象new Book("3");//new Book("4");System.gc();    //调用系统的垃圾回收器,强制进行终结动作,会调用系统中没有被清理的对象的finalize方法,输出的结果会是最近一个对象book3}}class Book{private boolean checkout;private String name;public Book(String s){checkout=false;name=s;}public void checkout(){checkout=true;System.out.println("check out the book "+name);}protected void finalize(){    //override finalize方法if(!checkout){System.err.println("book "+name+" hadn't been checked out--Garbage Collection");this.checkout();}else{System.out.println("Normal checked");}}}


3、 垃圾回收器
    JVM garbage collector 的特点是: 自适应auto-fit、分代的generation count、停止-复制 stop-copy、标记-清扫mark-sweep
    stop-copy: 是将正在运行的程序暂停下来,把原来在堆中的对象复制到另一块堆内存中,更新引用所指向的对象。为的是使堆中对象紧凑排列,减少碎片,避免页错误,
                        方便以后新对象的堆内存分配
    mark-sweep:遍历所有对象的引用,找到存活着的对象并标记好,全部标记完成后,开始释放没有被标记的对象
    自适应:stop-copy非常耗费空间和时间,但是当内存中出现很多碎片,堆内存分配不容易时,选择这个是合理的;当对象很稳定,垃圾对象较少时使用mark-sweepj将
                会是一个不错的选择,JVM会检测这些对象的状态,然后选择合理的回收方式,这就是自适应。
    分代:   每个块都有相应的代数以记录是否还存活,没引用一次该对象就增加一次它的代数,经常被引用的对象就不会被stop-copy拷贝整理,减少页错误。


三、初始化顺序
  
        1) 成员变量的初始化会在构造函数之前,如
       
 class A {            int n=1;    //先执行这个            A(int n1, char c1){//最后执行                System.out.println("n="+n+"  c="+c);                this.n=n1;                this.c=c1;                 System.out.println("n="+n+"  c="+c);            }                                    char c='b'; //再执行这个        }


    2)    静态数据的初始化只有在必要时才进行,不用他它就不初始化,创建了该对象的实例或者直接用类调用了他才会初始化仅此一次,跟它在代码中的位置无关
             静态数据的位置与它初始化的顺序毫无关系,它先于成员变量初始化,然后又构造方法初始化
            以下代码可以更好的理解这些:
      
  public class StaticIntialize{static B b=new B(1);//静态成员public static void main(String args[]){System.out.println("main ()"); }static B b2=new B(2);//静态成员}class A {A(int id){System.out.println("create A"+id);}}class B{static A sa1=new A(1);//静态成员private A aB=new A(2);//成员变量B(int id){ System.out.println("new a B"+id);}static A sa2=new A(3);//静态成员}//结果:create A1create A3create A2new a B1create A2new a B2main ()


四、 枚举类型enum

    关键字enum修饰的类,跟其他类其实差不多,只是有些新的特性,它里面的每个元素都有一个整数值,即出现的顺序,调用ordinal()可呈现
    可以在switch( EnumObject) case A: ....   
    写个例子就很熟悉了:

    
public enum enumLetter{A_PLUS("A+",5.0),    A_MINUS("A-",4.6),B_PLUS("B+",4.1),    B_MINUS("B-",3.6),C_PLUS("C+",3.1),    C_MINUS("C-",2.6),D_PLUS("D+",2.1),    D_MINUS("D-",1.6);private final String grade;private final double point;private enumLetter(String grade,double point){this.grade=grade;this.point=point;}public String getGrade(){return grade;}public double getPoint(){return point;}public static void main(String[] args){enumLetter myGrade=enumLetter.A_PLUS;enumLetter hisGrade=enumLetter.A_MINUS;enumLetter herGrade=enumLetter.A_PLUS;System.out.println("my grade: "+myGrade+" order:"+myGrade.ordinal());System.out.println("his grade: "+hisGrade+" order:"+hisGrade.ordinal());System.out.println("her grade: "+herGrade+" order:"+herGrade.ordinal());System.out.println("my grade ==her grade? "+(herGrade==myGrade));System.out.println("my grade equals her grade? "+(herGrade.equals(myGrade)));System.out.println("enumLetter.valueOf(\"C_PLUS\"): "+enumLetter.valueOf("C_PLUS"));System.out.println("enumLetter.valueOf(\"C_PLUS\").getPoint(): "+enumLetter.valueOf("C_PLUS").getPoint());}}//结果my grade: A_PLUS order:0his grade: A_MINUS order:1her grade: A_PLUS order:0my grade ==her grade? truemy grade equals her grade? trueenumLetter.valueOf("C_PLUS"): C_PLUSenumLetter.valueOf("C_PLUS").getPoint(): 3.1    //可以直接通过值获得那个枚举对象    

五、访问权限控制

1、 权限
    public , protected, private , 同包访问 共四种
2、 细则
    每个Java源文件,只能有一个public 修饰的类,该类必须与文件同名,通常用它来包含主函数,其他的默认为同包访问权限
    除了内部类,其他任何的类不能是private 和protected 修饰的,这样会阻止外界创建该类,也就没什么存在的价值了。
    若不希望其他类创建该类的对象,可以将所有的构造方法都用private 来修饰,需要注意的是:
        该类的static 成员可以访问该private 修饰的构造方法,以此来创建实例,单例模式使用的就是这个特性,程序如下:
        
   
 public class Singleton {public static void main(String[] args){A.newInstance().showName();}}class A {private String name;private A(String s){this.name=s;}private static A single=new A("single instance");//唯一被创建的A的对象public static A newInstance(){//只有这一个对象可以返回return single;}public void showName(){//外界可以调用这个方法来获得A的属性System.out.println("my name is "+name);}}

0 0
原创粉丝点击