Java编程思想之初始化与清理

用构造器确保初始化:通过构造器,确保每个对象都被初始化。构造器名字与类名相同。在创建对象时分配空间,并调用相应的构造器完成初始化。在java中,初始化和创建是捆绑在一起的,不能分离。构造器是一种特殊的方法,没有返回值。

方法重载:方法名相同而形式参数不同,每个重载的方法靠形式参数列表来区分。当传入的实际参数类型小于形式参数类型,会自动转换,实际数据类型会提升(对于char类型,会转变为int类型)。如果传入的实际参数大于形式参数,需要进行显示窄化转换。

缺省构造器(缺省、无参):当写的类中没有构造器,编译器自动创建。若定义了有参构造器,则必须手动定义无参构造器。

this关键字:编译器暗自把“所操作对象的引用”作为第一个参数传给方法。假如希望在方法内部获得对正在调用该方法的当前对象的引用,就用this,this只能在方法内部使用。如果方法内需要调用同一个类的另一个方法,不需要this,可直接调用。

this还可以在构造其中调用构造器。一个构造器只能调用一个其他构造器,且要放在最开始,否则报错。只能在构造器内调用,不得在其他地方用this调用构造器。

由this可理解static,在static方法内部不能调用非static方法,反过来却可以。一般static直接用类调用,不需要创建对象。在类中置入static方法就可以访问其他static方法和static域。

//调用类内其他方法可不用this
public class Apricot{
void pick(){......}
void pit(){pick();......) 
}

//用this表示对当前对象的引用
public class Leaf{
    int i=0;
    Leaf increment(){
        i++; 
        return this;
    }
    void print(){System.out.println("i="+i);}
    public static void main(String[] args){
         Leaf x=new Leaf();
         x.increment().increment().increment().print();  //i=3
    }
}

//this将当前对象传递给其他方法
 class Person {
     public void eat(Apple apple) {
         Apple peeled=apple.getPeeled();
         System.out.print("Yummy");
     }
}
class Peeler {
    static Apple peel(Apple apple) {
        //remove peel
        return apple; //peeled
    }
}
class Apple {
    Apple getPeeled() {
        return Peeler.peel(this);//用this将自身传递给外部方法
    }
}
public class PassingThis {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Person().eat(new Apple());
    }//Yummy
}
//this调用构造器
import static net.mindview.util.Print.*;
public class Flower {
    int petalCount=0;
    String s="initial value";
    Flower(int petals){
        petalCount=petals;
        print("Constructor w/ int arg only,petalCount= "+petalCount);
    }
    Flower(String ss){
        print("Constructor w/ String arg only,s="+ss);
        s=ss;
    }
    Flower(String s,int petals){
        this(petals);//只能调用一个,且要放在最开始
        this.s=s; //前一个s是成员,后一个s是参数
        print("String & int args");
    }
    Flower(){
        this("hi",47);
        print("default comstructor(no args)");
    }
    void printPetalCount() {
        print("petalCount="+petalCount+"S="+s);
    }
    public static void main(String[] args) {
        Flower x=new Flower();
        x.printPetalCount();
    }
}/*Output:
Constructor w/ int arg only,petalCount= 47
String & int args
default comstructor(no args)
petalCount=47S=hi
*/

清理终结处理和垃圾回收:对于不是new获得的特殊内存区域,由于垃圾回收器只回收new分配的内存,在这种情况下允许在类中定义finalize()方法来回收。finalize()先被调用,在下一次垃圾回收发生时,才会真正回收内存。常用finalize()来发现一些缺陷,以下示范一下。

对象可能不被垃圾回收;垃圾回收不等于“析构”;垃圾回收只与内存有关

class Book {
    boolean checkedOut=false;
    Book(boolean checkOut){
        checkedOut=checkOut;
    }
    void checkIn() {
        checkedOut=false;
    }
    protected void finalize() {
        if(checkedOut) {
            System.out.print("Error:checked out");
        }
    }
}
public class TerminationCondition {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Book novel =new Book(true);
        //proper cleanup
        novel.checkIn();
        //drop the reference,forget to clean up
        new Book(true);
        //force garbage collection&finalization
        System.gc();    //Error:checked out
    }
}

本例终结条件是:所有book对象在被gc前都被checkIn,但由于疏忽有一个没有checkIn就回收了,所以会打印出error。用finalize()来验证这个终结条件。

成员初始化:方法里的局部变量一定要初始化,而类中的字段可以被默认初始化为0、null、false。

构造器初始化:静态初始化只在必要时刻进行,在第一次被创建的时候进行,不可以再次初始化。

对象创建过程:1查找类路径,定位.class文件
          2载入.class,静态初始化
       3当new对象的时候,在堆上为对象分配存储空间
       4这块存储空间清零,自动将对象所有基本类型设置成默认值
       5执行所有出现于field定义处的初始化动作
       6执行构造器

//各种初始化发生的顺序(尤其注意静态初始化只执行一次)
//而实例初始化每次被调用都会执行
class Bowl { Bowl(int marker){ System.out.println("Bowl("+marker+")"); } void f1(int marker) { System.out.println("f1("+marker+")"); } } class Table { static Bowl bowl1=new Bowl(1);//----1 Table(){ //-----3 System.out.println("Table()"); bowl2.f1(1); } void f2(int marker) { System.out.println("f2("+marker+")"); } static Bowl bowl2=new Bowl(2);//-----2 } class Cupboard { Bowl bowl3=new Bowl(3); //------3 static Bowl bowl4=new Bowl(4);//------1 Cupboard(){ //------4 System.out.println("Cupboard()"); bowl4.f1(2); } static void f3(int marker) { System.out.println("f3("+marker+")"); } static Bowl bowl5=new Bowl(5);//-------2 } import static net.mindview.util.Print.*; public class StaticInitialization { public static void main(String[] args) { print("Creating new Cupboard() in main");//3 new Cupboard();//4,不再静态初始化 print("Creating new Cupboard() in main"); new Cupboard(); table.f2(1); Cupboard.f3(1); } static Table table= new Table();//1 static Cupboard cupboard=new Cupboard();//2 }/*output: Bowl(1) Bowl(2) Table() f1(1)- Bowl(4) Bowl(5) Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) f2(1) f3(1) */

数组初始化:数组的赋值只是赋了数组的引用。数组有个length固定成员,不可修改。对于引用类型的数组,new之后还是个引用数组,直到创建新的对象并赋给引用,才算完成初始化过程。使用空引用会出错。

static void printArray(Object... args){  //可变参数列表
  for(Object obj:args)
    print(obj+" ";
  println();
}

猜你喜欢

转载自www.cnblogs.com/yh-queen/p/11179149.html
今日推荐