第4章 初始化和清除(上)

4.1 用构建器自动初始化

4.2 方法过载

  4.2.1  区分过载方法

  4.2.2  主类型的过载

  4.2.3 返回值过载

  4.2.4 默认构建器

  4.2.5 t h i s 关键字  

4.3 清除:收尾和垃圾收集

  4.3.1 finalize()用途何在

  4.3.2 必须执行清除

4.4 成员初始化

  4.4.1 规定初始化

  4.4.2 构建器初始化

4.5 数组初始化

4.5.1 多维数组

4.6 总结

 

 

4.1 用构建器自动初始化(构造器的名字必须与类名完全相同)

package com.sunny.hello.c4;


public class SimpleConstructor {

    public static void main(String[] args) {
        for (int i=0; i< 10; i++){
            new Rock();
        }
    }
}

class Rock {
    Rock() {
        System.out.println("Creating Rock");
    }
}

运行结果:

Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock
Creating Rock

 

为构造器传入参数:

package com.sunny.hello.c4;


public class SimpleConstructor {

    public static void main(String[] args) {
        for (int i=0; i< 10; i++){
            new Rock(i);
        }
    }
}

class Rock {
    Rock(int i) {
        System.out.println("Creating Rock number " + i);
    }
}

运行结果:

Creating Rock number 0
Creating Rock number 1
Creating Rock number 2
Creating Rock number 3
Creating Rock number 4
Creating Rock number 5
Creating Rock number 6
Creating Rock number 7
Creating Rock number 8
Creating Rock number 9

构建器属于一种较特殊的方法类型,因为它没有返回值。这与 void 返回值存在着明显的区别。对于 void 返
回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。

 

4.2 方法过载

package com.sunny.hello.c4;


public class Overloading {

    public static void main(String[] args) {

        Tree t = new Tree(0);
        t.info();
        t.info("overload method");
        new Tree(); //Overload constructor
    }
}

class Tree {
    int height;
    Tree() {
        System.out.println("Planting a seedling");
        height = 0;
    }
    Tree(int i) {
        System.out.println("Creating new Tree that is " + i + " feet tall");
        height = i;
    }
    void info() {
        System.out.println("Tree is " + height + " feet tall");
    }
    void info(String s) {
        System.out.println(s + ":Tree is " + height + " feet tall");
    }
    static void print(String s) {
        System.out.println(s);
    }
}

运行结果:

Creating new Tree that is 0 feet tall
Tree is 0 feet tall
overload method:Tree is 0 feet tall
Planting a seedling

 

  4.2.1  区分过载方法

package com.sunny.hello.c4;

public class OverloadingOrder {

    public static void main(String[] args) {
        print("String first", 11);
        print(99, "Int first");
    }

    static void print(String s, int i) {
        System.out.println("String: " + s + ", int: " + i);
    }

    static void print(int i, String s) {
        System.out.println("int: " + i + ", String: " + s);
    }
}

运行结果:

String: String first, int: 11
int: 99, String: Int first

两个 print()方法有完全一致的自变量,但顺序不同,可据此区分它们。

 

  4.2.2  主类型的过载

package com.sunny.hello.c4;

public class PrimitiveOverloading {

    void f1(char x) {
        System.out.println("f1(char)");
    }
    void f1(byte x) {
        System.out.println("f1(byte)");
    }
    void f1(short x) {
        System.out.println("f1(short)");
    }
    void f1(int x) {
        System.out.println("f1(int)");
    }
    void f1(long x) {
        System.out.println("f1(long)");
    }
    void f1(float x) {
        System.out.println("f1(float)");
    }
    void f1(double x) {
        System.out.println("f1(double)");
    }


    void f2(byte x) {
        System.out.println("f2(byte)");
    }
    void f2(short x) {
        System.out.println("f2(short)");
    }
    void f2(int x) {
        System.out.println("f2(int)");
    }
    void f2(long x) {
        System.out.println("f2(long)");
    }
    void f2(float x) {
        System.out.println("f2(float)");
    }
    void f2(double x) {
        System.out.println("f2(double)");
    }


    void f3(short x) {
        System.out.println("f3(short)");
    }
    void f3(int x) {
        System.out.println("f3(int)");
    }
    void f3(long x) {
        System.out.println("f3(long)");
    }
    void f3(float x) {
        System.out.println("f3(float)");
    }
    void f3(double x) {
        System.out.println("f3(double)");
    }


    void f4(int x) {
        System.out.println("f4(int)");
    }
    void f4(long x) {
        System.out.println("f4(long)");
    }
    void f4(float x) {
        System.out.println("f4(float)");
    }
    void f4(double x) {
        System.out.println("f4(double)");
    }


    void f5(long x) {
        System.out.println("f5(long)");
    }
    void f5(float x) {
        System.out.println("f5(float)");
    }
    void f5(double x) {
        System.out.println("f5(double)");
    }


    void f6(float x) {
        System.out.println("f6(float)");
    }
    void f6(double x) {
        System.out.println("f6(double)");
    }


    void f7(double x) {
        System.out.println("f7(double)");
    }

    void testConstVal() {
        System.out.println("Testing with 5");
        f1(5);
        f2(5);
        f3(5);
        f4(5);
        f5(5);
        f6(5);
        f7(5);
    }

    void testChar() {
        char x = 'x';
        System.out.println("char argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testByte() {
        byte x = 0;
        System.out.println("byte argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testShort() {
        short x = 0;
        System.out.println("short argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testInt() {
        int x = 0;
        System.out.println("int argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testLong() {
        long x = 0;
        System.out.println("long argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testFloat() {
        float x = 0;
        System.out.println("float argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    void testDouble() {
        double x = 0;
        System.out.println("double argument:");
        f1(x);
        f2(x);
        f3(x);
        f4(x);
        f5(x);
        f6(x);
        f7(x);
    }

    public static void main(String[] args) {
        PrimitiveOverloading p = new PrimitiveOverloading();
        p.testConstVal();
        p.testChar();
        p.testByte();
        p.testShort();
        p.testInt();
        p.testLong();
        p.testFloat();
        p.testDouble();

    }
}

运行结果:

Testing with 5
f1(int)
f2(int)
f3(int)
f4(int)
f5(long)
f6(float)
f7(double)
char argument:
f1(char)
f2(int)
f3(int)
f4(int)
f5(long)
f6(float)
f7(double)
byte argument:
f1(byte)
f2(byte)
f3(short)
f4(int)
f5(long)
f6(float)
f7(double)
short argument:
f1(short)
f2(short)
f3(short)
f4(int)
f5(long)
f6(float)
f7(double)
int argument:
f1(int)
f2(int)
f3(int)
f4(int)
f5(long)
f6(float)
f7(double)
long argument:
f1(long)
f2(long)
f3(long)
f4(long)
f5(long)
f6(float)
f7(double)
float argument:
f1(float)
f2(float)
f3(float)
f4(float)
f5(float)
f6(float)
f7(double)
double argument:
f1(double)
f2(double)
f3(double)
f4(double)
f5(double)
f6(double)
f7(double)

若我们的数据类型“小于“方法中使用的自变量,就会对那种数据类型进行”转型“处理。char类型稍有不同,它会转型为int。若自变量”大于“过载方法期望的自变量,会怎样呢?

package com.sunny.hello.c4;

public class Denotion {

    static void print(String s) {
        System.out.println(s);
    }


    void f1(char x) {
        System.out.println("f1(char)");
    }
    void f1(byte x) {
        System.out.println("f1(byte)");
    }
    void f1(short x) {
        System.out.println("f1(short)");
    }
    void f1(int x) {
        System.out.println("f1(int)");
    }
    void f1(long x) {
        System.out.println("f1(long)");
    }
    void f1(float x) {
        System.out.println("f1(float)");
    }
    void f1(double x) {
        System.out.println("f1(double)");
    }


    void f2(char x) {
        System.out.println("f2(char)");
    }
    void f2(byte x) {
        System.out.println("f2(byte)");
    }
    void f2(short x) {
        System.out.println("f2(short)");
    }
    void f2(int x) {
        System.out.println("f2(int)");
    }
    void f2(long x) {
        System.out.println("f2(long)");
    }
    void f2(float x) {
        System.out.println("f2(float)");
    }


    void f3(char x) {
        System.out.println("f3(char)");
    }
    void f3(byte x) {
        System.out.println("f3(byte)");
    }
    void f3(short x) {
        System.out.println("f3(short)");
    }
    void f3(int x) {
        System.out.println("f3(int)");
    }
    void f3(long x) {
        System.out.println("f3(long)");
    }


    void f4(char x) {
        System.out.println("f4(char)");
    }
    void f4(byte x) {
        System.out.println("f4(byte)");
    }
    void f4(short x) {
        System.out.println("f4(short)");
    }
    void f4(int x) {
        System.out.println("f4(int)");
    }


    void f5(char x) {
        System.out.println("f5(char)");
    }
    void f5(byte x) {
        System.out.println("f5(byte)");
    }
    void f5(short x) {
        System.out.println("f5(short)");
    }


    void f6(char x) {
        System.out.println("f6(char)");
    }
    void f6(byte x) {
        System.out.println("f6(byte)");
    }


    void f7(char x) {
        System.out.println("f7(char)");
    }


    void testDouble() {
        double x = 0;
        System.out.println("double argument:");
        f1(x);
        f2((float)x);// 必须强转,否则编译不通过
        f3((long)x);
        f4((int)x);
        f5((short) x);
        f6((byte)x);
        f7((char)x);
    }

    public static void main(String[] args) {
        Denotion d = new Denotion();
        d.testDouble();
    }
}

运行结果:

double argument:
f1(double)
f2(float)
f3(long)
f4(int)
f5(short)
f6(byte)
f7(char)

 

  4.2.3 返回值过载

不能根据返回值类型来区分重载的方法。比如,void f(){},int f() {},编译器如果去调用f方法,无法判断到底是调用了哪个方法。

  4.2.4 默认构建器

package com.sunny.hello.c4;

public class DefaultConstructor {

    public static void main(String[] args) {
        Bird bird = new Bird(); //调用默认构造器
        System.out.println(bird.i); // 0
    }
}
class Bird {
    int i;
}

若以上代码改成:

package com.sunny.hello.c4;

public class DefaultConstructor {

    public static void main(String[] args) {
        Bird bird = new Bird(); //编译报错
        System.out.println(bird.i);
    }
}
class Bird {
    int i;
    Bird(int i){
        
    }
}

 如果在类中添加了有参构造器,那么,编译器就不会再提供默认的无参构造器。如果想调用无参构造器,必须显示声明无参构造器。修改如下:

package com.sunny.hello.c4;

public class DefaultConstructor {

    public static void main(String[] args) {
        Bird bird = new Bird();
        System.out.println(bird.i);
    }
}
class Bird {
    int i;
    Bird() {

    }
    Bird(int i){

    }
}

 

  4.2.5 t h i s 关键字  

package com.sunny.hello.c4;


public class Leaf {
    private 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
    }
}

由于 increment()通过 this 关键字返回当前对象的句柄,所以可以方便地对同一个对象执行多项操作。

 

1.  在构建器里调用构建器 

package com.sunny.hello.c4;


public class Flower {

    private int petalCount = 0;
    private String s = new String("null");

    Flower(int petals) {
        petalCount = petals;
        System.out.println("Constructor int arg only, petalCount = " + petalCount);
    }

    Flower(String ss) {
        s = ss;
        System.out.println("Constructor String arg only, s = " + ss);
    }

    Flower(String ss, int petals) {
        this(petals);
       // this(s); 编译报错,can not call two!
        this.s = s; //Another use of "this"
        System.out.println("String & int arg");
    }

    Flower() {
        this("hi", 47);
        System.out.println("default constructor (no args)");
    }

    void print() {
        // this(11); 编译报错,不能在非构造器中调用this构造器
        System.out.println("petalCount = " + petalCount + " s = "+ s);
    }

    public static void main(String[] args) {
        Flower x = new Flower();
        x.print();
    }
}

运行结果:

Constructor int arg only, petalCount = 47
String & int arg
default constructor (no args)
petalCount = 47 s = null

尽官可用this调用一个构造器,但是不可调用两个。

除此之外,构造器调动必须是做的第一件事情,否则会收到编译不通过。也就是,以上代码中的this调用都必须是方法体中的第一行,否则编译报错。

print方法说明,编译器不让我们从除了一个构造器之外的其他任何方法内部调用一个构造器。

 

2. static的含义

package com.sunny.hello.c4;


public class StaticMethod {

private static int i;

public static void print(int i) {
//showNumber(i); 编译报错
// System.out.println(this.i); 静态方法中不能引用this
System.out.println(i);

}

public int showNumber(int i){
print(i); // 0
return i;
}

public static void main(String[] args) {
print(0); // 0
}
}

static不是面向对象的,非静态方法,只有对象才可以调用,而静态方法,可以不需要实例化对象,直接通过类名去调用。

静态方法中只能调用非静态方法,而非静态方法中是可以调用静态方法的。

 

4.3 清除:收尾和垃圾收集

为什么要引入finalize()方法?

假如我们的对象分配了一个”特殊“内存区域,没有使用new。垃圾收集器只知道释放那些由new分配的内存,所以不知道该如何释放对象的”特殊“内存。为了解决这个问题,java提供了一个名为finalize()方法。

finalize()工作原理:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作。

例如:假设在对象创建过程中,它会将自己描绘到屏幕上,如果不从屏幕上明确删除它的图像,那么它可能永远都不会被清除。若在finalize()里置入某种删除机制,那么假设对象被当做垃圾收掉了,图像会首先将自身从屏幕上移去。但

若未被收掉,图像就会被保留下来。

  4.3.1 finalize()用途何在

之所以要使用finalize(),看起来似乎是由于有时需要采取与java的普通方法不同的一种方法,通过分配内存来做一些具有C风格的事情。这主要通过”固有方法“来进行。它是从java里调用非java方法的一种方式。在非java代码内部,也许能调用C的

mallac()系列函数,用它分配存储空间。而且除非调用了free(),否则存储空间不会得到释放,从而造成内存”漏洞“的出现。当然,free()是一个C和C++函数,所以我们需要在finalize()内部的一个固有方法中调用它。

  4.3.2 必须执行清除

finalize()最有用处的地方之一是观察垃圾收集的过程。

package com.sunny.hello.c4;

public class Garbage {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: \n" + "java Garbage before\n  or:\n" + "java Garbage after");
            return;
        }
        while (!Chair.f) {
            new Chair();
            new String("To take up space");
        }
        System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created +
                ", total finalized = " + Chair.finalized);
        if (args[0].equals("before")) {
            System.out.println("gc():");
            System.gc();
            System.out.println("runFinalization():");
            System.runFinalization();
        }
        System.out.println("bye!");
        if (args[0].equals("after")) {
            System.runFinalizersOnExit(true);
        }
    }
}

class Chair {
    static boolean gcrun = false;
    static boolean f = false;
    static int created = 0;
    static int finalized = 0;
    int i;

    Chair(){
        i = ++created;
        if (created == 47) {
            System.out.println("Created 47");
        }
    }

    protected void finalize() {
        if (!gcrun) {
            gcrun = true;
            System.out.println("Beginning to finalize after" + created + " Chairs have been created");
        }
        if (i == 47) {
            System.out.println("Finalizing Chair #47, " + "Setting flag to stop Chair creation");
            f = true;
        }
        finalized++;
        if (finalized >= created) {
            System.out.println("All " + finalized + " finalized");
        }
    }
}

 有待继续深入理解。

 

posted @ 2017-12-13 14:20  凌晨六点半  阅读(271)  评论(0编辑  收藏  举报