Java 初始化和清理

一、constructor

I skipped it!

二、overload

1、是否重载,与返回值类型无关,只与参数列表有关,另外:
public void m1(Integer integer) {}

public void m1(int i ){}
也能构成overload。
2、以基本类型作为参数的overload,当传入的数据类型(实际参数类型)“小于”形参,实际数据类型就会被提升。

三、this 关键字

1、先抛个问题:
编译器是如何知道Peel是被 a 还是b 所调用?

public class BananaPeel {

    public static void main(String[] args) {
        Banana a = new Banana();
        Banana b = new Banana();
        a.peel(1);
        b.peel(2);
    }
}

class Banana{
    void peel(int i) {

    }
}

原来,编译器做了一些额外的工作,它把“所操作对象的引用传递作为第一个参数传递给了Peel()”,所以实际的内部调用形式是:

Banana.peel(a,1)
Banana.peel(b,2)

若希望在方法内部获取对当前对象的引用(或者叫:调用方法的按个对象的引用),可使用this关键字来表示

2、 再举个例子

这个例子通过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) {
        // 由于 increment()返回的原来调用方对象的引用,所以下例中 leaf 与leaf1 其实是同一个对象
        // 如此,很容易在一条语句中对同一个对象执行多次操作
        Leaf leaf = new Leaf();
        Leaf leaf1 = leaf.increment().increment().increment();
        System.out.println(leaf == leaf1);
        leaf.print(); // i = 3
        leaf1.print();// i = 3
    }
}

下面这个例子使用this关键字将当前对象传递给其他方法
实际生产中,大概没人这样写的的吧?

public class Person {
    public void eat(Apple apple) {
        Apple peeledApple = apple.getPeeledApple();
        System.out.println(" eated it!");
    }
}

// “削苹果”的工具类。由于某种原因,必须要将该工具类放置到Apple外部,比如该外部方法要应用于许多不同的类,但我们不想重复
// 这些代码
class Peeler{
    static Apple peel(Apple apple) {
        /*peel process*/
        return apple;
    }
}

// 传入一个苹果,返回“削完”后的苹果,但是****其实还是同一个苹果****
class Apple{
    Apple getPeeledApple() {
        // 传入的是一个this,即一个 Apple对象
        return Peeler.peel(this);
    }
}

class PassingThisTest{
    public static void main(String[] args) {
        new Person().eat(new Apple());
    }
}

四、this用于构造器调用

使用this可在一个构造器中调用另一个构造器,以避免重复代码。
在普通方法中,this指的是“这个对象”或者“当前对象”,而其本身表示对当前对象的引用。而在构造器中,this后有了参数列表,则含义不同,那将表示对符合该参数列表的某个构造器的调用。
需要注意的是,构造器中调用this() ,必须将该句放置在构造方法中的第一行。

public class Flower {

    int petalCount = 0;
    String s = " initial value ";

    public Flower(int petalCount) {
        System.out.println("----");
        this.petalCount = petalCount;
    }

    public Flower(String s) {
        System.out.println("+++++");
        this.s = s;
    }

    public Flower(int petalCount, String s) {
        this(petalCount);
        this.s = s;
        System.out.println("......");
    }

    public Flower() {
        this(10, " hana ");
        System.out.println(" no-param constructor ");
    }

    public static void main(String[] args) {
        Flower flower = new Flower();
        System.out.println(flower.petalCount);
        System.out.println(flower.s);
    }
}

五、清理对象和GC

TODO

六、初始化

6.1 成员初始化

两点:
1、局部变量,必须手动初始化
2、全局变量,即使不手动初始化,编译器也会赋初始值

6.2 构造器初始化

6.2.1 初始化顺序

6.2.2 静态数据初始化

1、无论创建多少个对象,静态数据只占用一份内存
2、先初始化静态对象(如果之前没有初始化的话),然后初始化“非静态对象”

6.2.3 静态代码块

1、只执行一次!随着类的加载而加载

6.2.4 代码块(实例初始化)

在实例化每个对象时,代码块中的代码 一定会执行,不论是使用无参还是有参构造器来初始化,而且 代码块中的代码在 构造器之前执行。

所以总的来说:初始化顺序是:
类变量 --> 静态代码块 --> 构造器 --> 代码块

七、数组初始化

数组的创建是在运行时进行的。
数组元素中的基本数据类型会自动初始化为空值,对于布尔值,即为FALSE;对于数字和字符,即为0;
而对于元素是引用类型的数组,其元素会自动初始化为null。

猜你喜欢

转载自blog.csdn.net/qq_30118563/article/details/83045365