java 编程思想 阅读笔记(3)

java 编程思想 阅读笔记(3)

默认构造器

不接受任何参数的构造器叫做默认构造器
如果你写的类中没有构造器,编译器会自动帮你创建一个默认构造器

如果已经定义好了一个构造器,这时候就不会帮你创建默认构造器了

因为这时候可能是不想要默认构造器(我遇到过这个问题,默认构造器导致所有的对象字段都是 null,会导致 NullPointer 异常

在构造器中调用构造器

必须把构造器放在最起始处,而且在一个构造器里只能调用 this(…) 其他构造器一次

static 的含义

在 static 方法内部不能调用非 static 方法, 反之可以

清理:终结处理额垃圾回收

之所以要有 finalize()方法,是因为分配内存时候使用了类似 c 语言的做法,主要是本地方法(native method)

如果你打开了其他资源(比如 sql connection 或者文件),记得在其他方法(不是 finalize)里 close

引用计数方式

当有引用连接至对象时,+1;当引用离开作用域或被置为 null 时候,-1。 当某个对象引用为0时候,回收。
对于循环引用,可能会出现“对象应该被回收,但引用计数却不为0”的情况。

java 虚拟机 垃圾回收

从栈或静态存储区的引用开始,遍历所有的引用

停止-复制

先暂停程序的运行,然后把所有存活的对象从当前堆复制到另外一个堆,没有被复制的全部都是垃圾。可以把原来的一块区域全部情况,保证内存块的完整性。
对象被复制到新堆时候,也是紧凑排列的。
这对于大量的短命的对象很有用

标记-清扫

垃圾很少时候,可以用标记-清扫,这时候速度比上面的停止-复制快。
jvm 应该会用一个自适应的算法,可能会有个阈值(判决条件),从这几种垃圾回收算法中切换。
这样容易产生碎片,可以使用标记-整理方法
总结就是 自适应的、分代的、停止-复制、标记-清扫

Just-In-Time 即时编译

编译器只在必要的时候,才会编译字节码。这样不会被执行的字节码就不会被编译,而且执行次数越多,随着优化的进行,代码速度越快。

静态数据的初始化

静态数据成员在第一次对象创建(或者第一次访问静态数据)时候会被初始化,此后,静态对象不会再被初始化。


public class HttpFind {

    public static void main(String[] args) {
        System.out.println("inside main()");
        Cups.c1.f(2);
        // new Cups().c1.f(2);
    }

}

class Cup {
    Cup(int marker) {
        System.out.println("Cup( " + marker + " )");
    }

    void f(int marker) {
        System.out.println("f( " + marker + " )");
    }
}

class Cups {
    static Cup c1 = new Cup(1);
    static Cup c2 = new Cup(2);

    Cups() {
        System.out.println("in Cups constructor");
    }

}
输出为
inside main()
Cup( 1 )
Cup( 2 )
f( 2 )

如果改为

public static void main(String[] args) {
        System.out.println("inside main()");
        // Cups.c1.f(2);
        new Cups().c1.f(2);
    }

输出为

inside main()
Cup( 1 )
Cup( 2 )
in Cups constructor f( 2 )

多了 Cups 构造器的部分,说明如果只是使用类的静态成员,最后并不构造该类(因为构造函数都没有被调用)

可变参数

public static void main(String[] args) {
        f(1, 2, 3);
        f(new int[] { 11, 22, 33 });
    }

    public static void f(int... args) {
        for (int arg : args) {
            System.out.println(arg);
        }
    }

看这个代码,可变参数在第一次调用会自动把参数列表转化为数组。而第二次调用,传递的值已经是个数组里,就没有必要再转化为数组。

Note
你应该在总是在重载方法的一个版本上使用可变参数,或者根本不使用它。

枚举类型


public class HttpFind {

    public static void main(String[] args) {
        for (Spiciness s : Spiciness.values()) {
            System.out.println(s);
        }
        System.out.println(Spiciness.MEDIUM);
    }

}

enum Spiciness {
    NOT, MILD, MEDIUM
}

输出

NOT
MILD
MEDIUM
MEDIUM

你可能感兴趣的:(java,编程,对象,阅读,编译器)