this关键字
this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。如果在方法内部调用同一个类的另一个方法,就不必使用this,直接调用即可。当前方法中的this引用会自动应用于同一类中的其他方法。
public class Apricot{
void pick(){}
void pit(){pick();}
}
在pit()内部,可以写this.pick(),但无此必要,编译器能帮你自动添加。只有当需要明确指出对当前对象的引用,才需要使用this关键字。
垃圾回收
引用计数:
是一种简单但是速度很慢的垃圾回收技术,每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或者被置为null时,引用计数减1。虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为0时,就释放其占有的空间(引用计数模式经常会在计数值变为0时立即释放对象)。这种方法有个缺陷,如果对象之间存在循环引用,可能会出现“对象应该被回收,但引用计数却不为0”的情况。对垃圾回收器而言,定位这样的交互自引用的对象组所需要的工作量极大。
停止-复制:
先暂停程序的运行,然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全都时垃圾。
标记-清扫:
从堆栈和静态存储区出发,遍历所有的引用,进而找出所有的存活对象,每当找到一个存活对象,就会给对象设一个标记,这个过程那个中不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始,在清理过程中,没有标记的对象将被释放。
初始化
成员初始化:
Java尽力保证所有的变量在使用之前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。如:
void f(){
int i;
i++; //Error -- i not initialized
}
要是类的数据成员(即字段)是基本类型,情况会有所不同,类的每个基本类型数据成员保证都会有一个初始值。如:
public class InitialValues{
int i;
void printInitialValues(){
System.out.println(i);
}
public static void main(String[] args){
new InitialValues.printInitialValues();
}
}/* Output: 0 */
构造器初始化:
在类的内部,变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
class Window{
Window(int i){System.out.println("Window("+i+")");}
}
class House{
Window w1 = new Window(1);
House(){
System.out.println("House()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f(){System.out.println("f()");}
Window w3 = new Window(3);
}
public class OrderOfInitialization{
public staitc void main(String[] args){
House h = new House();
h.f();
}
}/* Output:
Window(1)
Window(2)
Window(3)
House()
Window(33)
f() */
静态数据的初始化:
无论创建多少个对象,静态数据都只占用一份存储区域。初始化的顺序是先静态对象,然后是非静态对象。
Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(静态块)。如:
public class Spoon {
static int i;
static {
i = 47;
}
}
枚举类型:
public enum Spiciness{
NOT,MILD,MEDIUM,HOT,FLAMING
}
创建一个枚举类型,他有5个具名值。因为枚举类型的实例是常量,所以用大写字母表示。
为了使用enum,需要创建一个该类型的引用,并将其赋值给某个实例:
public class SimpleenumUse{
public static void main(String[] args){
Spiciness howHot = Spiciness.MEDIUM;
System.out.println(howHot);
}
}/* Output:
MEDIUM */