类的初始化
方法重载
如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载函数
- java通过参数列表的不同来进行方法的重载
- 参数的顺序也可作为区分方法的依据(不推荐)
- 返回值类型不能作为区分方法的依据
- 基本数据类型可以自动进行类型提升(可能造成混淆),如果找不到恰好接受char型的方法,就会把char型提升为int型
this关键字
编译器会隐式地把所操作对象的引用作为第一个参数传递给通过这个对象调用的方法。
this关键字只能在方法内部使用,用来表示调用方法的那个对象,如果在一个方法内部调用同一个类的其他方法就不使用this关键字。
this关键字也可用于将当前对象传递给其他方法。
构造器
Java中的构造器类似于C++的构造方法,在实例化对象时被调用,构造器名与类名相同,没有返回值类型声明,虽然没有static关键字,但实际用法与静态方法相似。如果不自己声明构造器,编译器会生成一个默认的无参构造器,如果自己声明了构造器,编译器就不会再生成默认无参构造器。
- 构造器可以重载
- 在构造器内可以用this关键字调用其他构造器,但只能调用一次,且必须在第一条语句调用
静态数据初始化
class Person{
static String[] language;
static {
language = new String[]{"chinese", "English"};
System.out.println(language[1]+language[0]);
}
Person(){System.out.println("ii");}
}
public class Test1{
public static void main(String[] args) {
Person[] k=new Person[2];
for(Person i:k){
i = new Person();
}
}
}
执行结果:
Englishchinese
ii
ii
static关键字后的代码块会先于构造器被调用,对静态变量进行初始化
非静态成员初始化
class Person{
String[] language;
{
language = new String[]{"chinese", "English"};
System.out.println(language[1]+language[0]);
}
Person(){System.out.println("ii");}
}
public class Test1{
public static void main(String[] args) {
Person[] k=new Person[2];
for(Person i:k){
i = new Person();
}
}
}
具体语法与静态初始化相似,但是执行结果并不相同
Englishchinese
ii
Englishchinese
ii
静态变量的初始化只在类第一次初始化时进行,而非静态变量的初始化每次初始化对象时都会进行。
总结
- 当首次创建对象时,或者类的静态成员被首次访问时,Java解释器必须查找类的路径,以定位类的.class文件
- 然后载入.class文件(创建一个对象),有关的静态初始化会被进行(静态初始化只进行一次的原因)
- 用new关键字创建对象时,首先在堆上为对象分配存储空间,然后这块空间会被清零(使对象中所有基本类型恢复默认值)
- 执行出现于字段定义处的初始化动作
- 执行构造器
垃圾回收与清理
原则
- 对象可能不被回收
- 垃圾回收不等于析构
- 垃圾回收只与内存有关
finalize关键字
finalize()方法会在对象被回收前调用,但它不同于C++中的析构方法,因为java中的对象不一定被回收,所以它不一定会被调用,也可以通过System.gc()方法强制回收。
垃圾回收器工作
在C/C++中,在堆上分配内存的效率比较低,因为它们利用堆内存不连续。而Java的堆内存像一条传送带,每分配一个新对象就像前移动一格,对象分配效率较高。而堆内存的连续与垃圾回收机制密切相关。
“复制——停止方式”
先暂停程序运行,然后将所有活的对象从当前的堆复制到另一个堆,没有被复制的全都被回收。当对象被复制到新的堆时,它们是紧凑排列的。
“标记——清扫方式”
从堆栈和静态存储区开始,遍历所有引用,找出所有存活的对象,每找到一个存活的对象,就给对象一个标记(这个过程中不会回收任何对象),标记工作结束后,才会开始清理工作。所以清理后的堆是不连续的,只有在已知只有很少的垃圾要被回收是,“标记——清扫方式”效率较高。
垃圾回收器工作模式
如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到“标记——清扫”方式,要是出现了很多堆内存碎片,就会切换回“复制——停止”方式。