Thinking in Java 笔记(二)

一、方法重载 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 A1
create A3
create A2
new a B1
create A2
new a B2
main ()


四、 枚举类型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:0
his grade: A_MINUS order:1
her grade: A_PLUS order:0
my grade ==her grade? true
my grade equals her grade? true
enumLetter.valueOf("C_PLUS"): C_PLUS
enumLetter.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);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值