构造函数重载: 重载三要素(参数数量、参数类型、参数的排列顺序)。
基本数据类型的重载: 如果实参比形参的类型小,数据会先提升,如果实参比形参大,那么要先进行强制类型转换。
返回值类型不是重载的要素: 理解之一是,构造函数要实现重载,但构造函数无返回值。另外调用函数的时候可以没有返回值类型。
this关键词的使用:
1、this只能用于方法内部,它负责返回调用这个方法的对象的引用。你可以把this对象的引用当成任何对象的引用。
2、this用于在构造函数中调用其他构造函数,但只能调用一个,且调用的代码应放在程序最前面,否则编译器会报错。
3、this.s=s当类的数据成员与类的方法的参数同名时,使用this.s=s消除歧义。
static的含义:
它的意思是,这个方法没有this,你不能在static方法里调用非static的方法,但你却可以不通过对象,直接调用static方法。类的static方法只能访问其它static方法static成员。垃圾回收:
java提供finalize()方法用于垃圾回收器回收前执行方法中的代码进行非new所创建内存的清理。你可以自己定义类的finalize()方法。不过要注意java对象并不总是会被回收的。它不象C++一样提供析构函数,可做到总是回收。java垃圾回收特点:
1、对象不一定会被垃圾回收器回收;
2、垃圾回收不是析构;
3、你可以自己写方法时行垃圾回收;
4、垃圾回收只与内存有关;
5、垃圾回收和finalize()都是靠不住的,只要jvm还没到快要耗尽内存的地步,它是不会浪费时间来回收垃圾以恢复内存的。
初始化的顺序: 初始化的顺序是由变量在类的定义里面的顺序所决定的 。 变量的定义可能会分散在类定义的各个地方 , 并且与方法的定义相互交错,但是变量的初始化会先于任何方法,甚至是构造函数的调用。以下为例:
class Tag{
Tag(int marker){输出结果为:
System.out.println("Tag("+marker+")");
}
}
class Card{
Tag t1 = new Tag(1);
Card(){
System.out.println("Card()");
t3 = new Tag(22);
}
Tag t2 = new Tag(2);
void f(){
System.out.println("f()");
}
Tag t3 = new Tag(3);
}
public class Clean {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Card t = new Card();
t.f();
}
}
Tag(1)
Tag(2)
Tag(3)
Card()
Tag(22)
f()
Static数据的初始化(注意结合代码调试理解):
package com.initialization.order;
class Bowl {
Bowl(){
System.out.println("Bowl(9)");
}
Bowl(int marker) {
System.out.println("Bowl(" + marker + ")");
}
static Bowl b6 = new Bowl(6);
static Bowl b9 = new Bowl();
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}class Table {
static Bowl b1 = new Bowl(1);
Table() {
System.out.println("Table()");
b2.f(1);
}
void f2(int marker) {
System.out.println("f2(" + marker + ")");
}
static Bowl b2 = new Bowl(2);
}
class Cupboard {
Bowl b3 = new Bowl(3);
Bowl b10 = new Bowl();
static Bowl b4 = new Bowl(4);
Cupboard() {
System.out.println("Cupboard()");
b4.f(2);
}
void f3(int marker) {
System.out.println("f3(" + marker + ")");
}
static Bowl b5 = new Bowl(5);
}public class StaticInitialization {
//static Bowl b7 = new Bowl(7); //----------(1)
public static void main(String[] args) {
System.out.println(
"Creating new Cupboard() in main");
new Cupboard();
System.out.println(
"Creating new Cupboard() in main");
new Cupboard();
//t2.f2(1); //--------------(2)
//t3.f3(1); //---------------(3)
}
//static Bowl b8 = new Bowl(8); //----------------(4)
//static Table t2 = new Table(); //----------------(5)
//static Cupboard t3 = new Cupboard(); //---------(6)
} ///:~调试以上代码,总结出以下结论:
一、初始化的过程:总体来说顺序为:static初始化->非static初始化->执行构造函数;
二、代码分析一:对现有代码执行结果如下:
Creating new Cupboard() in main
Bowl(6)
Bowl(9)
Bowl(4)
Bowl(5)
Bowl(3)
Bowl(9)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Bowl(9)
Cupboard()
f(2)
执行过程:
1、java解释器寻找public class类,加载StaticInitialization 类;
2、寻找StaticInitialization 类中的static定义代码段;这里因为(1)、(4)、(5)、(6)均加了注释,所以StaticInitialization 中没有static需要初始化;3、进入main函数中执行代码输出Creating new Cupboard() in main ;
4、继续执行new Cupboard();,注意初始化的顺序是static初始化->非static初始化->执行构造函数; 所以加载类Cupboard后,首先寻找Cupboard类中的static代码段 ;
发现static段 是: static Bowl b4 = new Bowl(4); static Bowl b5 = new Bowl(5);
同时发现有非static段 是: Bowl b3 = new Bowl(3); Bowl b10 = new Bowl();
按顺序先执行:static Bowl b4 = new Bowl(4); 初始化,因为定义的是Bowl类的实例,所以先加载Bowl类 ,进入Bowl类发现又有static 代码段static Bowl b6 = new Bowl(6);
static Bowl b9 = new Bowl();然而我们知道初始化static Bowl b4 = new Bowl(4); 需要调用Bowl 的构造函数,但调用构造函数之前必须将该类需要初始化的部分先进行初始化,所以执行到这里就要先进行Bowl类中的static代码段的初始化,之后才能调用构造函数Bowl(int marker) 为static Bowl b4 = new Bowl(4); 进行初始化。 于是b6,b9分别调用构造函数Bowl(int marker),Bowl(),输出Bowl(6),Bowl(9), 完了之后,b4调用构造函数Bowl(int marker)输出 Bowl(4), b4初始化结束,返回Cupboard类继续执行,初始化b5,输出 Bowl(5) ,此时Cupboard类中static部分初始化完,接下来对非static部分初始化,即对b3和b10初始化, 一样的方法,加载Bowl类,发现static字段在上面已经初始化,所以这里直接调用Bowl类的构造函数,输出Bowl(3),Bowl(9)。 至此Cupboard类中需要初始化的部分已经初始化完了,所以放心大胆的调用Cupboard类的构造函数 ,为main函数中代码完成new Cupboard();的实现,输出Cupboard(),f(2)。 程序执行返回到main函数,输出:Creating new Cupboard() in main, 代码new Cupboard();又一次出现,这里实际上是想演示static只会初始化一次 ,而非static只要创建了对象或调用了成员、成员函数,会进行第二次初始化 ,于是可以看到输出结果并没有再 输出Bowl(6)、Bowl(9)、Bowl(4)、Bowl(5),而是输出:Bowl(3)、Bowl(9)、Cupboard()、f(2)。
5、取消注释(1)、(4),发现结果如下:
Bowl(6)
Bowl(9)
Bowl(7)
Bowl(8)
Creating new Cupboard() in main
Bowl(4)
Bowl(5)
Bowl(3)
Bowl(9)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Bowl(9)
Cupboard()
f(2)
可以看出输出了Bowl(7)、Bowl(8),这说明在main()函数执行之前,程序要先对StaticInitialization进行检查,如果有static部分,则先初始化。
6、再取消注释(2)、(5)输出结果为:
Bowl(6)
Bowl(9)
Bowl(7)
Bowl(8)
Bowl(1)
Bowl(2)
Table()
f(1)
Creating new Cupboard() in main
Bowl(4)
Bowl(5)
Bowl(3)
Bowl(9)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Bowl(9)
Cupboard()
f(2)
f2(1)
在前面的基础上又输出了Bowl(1)、Bowl(2)、Table()、f(1)。然而我们看到当没有代码
static Table t2 = new Table();的时候Table类中的static部分没有被初始化,这说明什么?
static初始化只有在必要的时候才会进行。只有在创建了第一个Table对象之后才会进行初始化。总结如下: 初始化顺序为:加载public StaticInitialization类->初始化static->加载类Cupboard->初始化static->加载类Bowl->初始化static->执行Bowl类构造函数->初始化Cupboard类非static->调用Bowl类构造函数执行->调用Cupboard类构造函数执行->返回StaticInitialization类.
上例中只涉及组合关系的类的初始化顺序,下文中对含有继承关系的初始化过程说明:
http://blog.csdn.net/luweifeng1983/archive/2009/11/02/4758730.aspx