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