Java编程思想 第五章 初始化与清理

Java编程思想 第五章 初始化与清理,第1张

Java编程思想 第五章 初始化与清理

文章目录
    • 5.1 用构造器确保初始化
    • 5.2 方法的重载
    • 5.4 this关键字
      • 5.4.1 在构造器中调用构造器
      • 5.4.2 static方法
    • 5.5 终极处理和垃圾回收
      • 垃圾回收器如何工作
    • 5.6 成员的初始化
      • 初始化顺序
      • 静态初始化、非静态初始化
    • 5.8 数组初始化
      • 可变参数列表
    • 5.9 枚举类型

5.1 用构造器确保初始化

Java中构造器采用与类相同的名称,防止构造器与类中的方法名冲突,同时方便编译器自动调用。每个方法小写的编码风格不适用于构造器。

构造器没有返回值,这与返回值为空(void)是不同的。

Java默认提供无参构造器,也可以自己编写有参数的构造器。如果已经定义了 一个构造器,编译器就不会自动创建默认构造器。

5.2 方法的重载

通过参数类型列表可以区分方法,参数的顺序不同也会用于区分。
根据方法的返回值来区分重载方法是行不通的。

5.4 this关键字

如果你希望在方法的内部获得对当前对象的引用,由于这个引用是由编译器偷偷传进来的,所以没有标识符可用。可以使用this关键字,this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。在方法内部调用同一个类的另一个方法,直接调用即可,不用this。

public class Person {
	Person getPerson() {
		return this;
	} 
	void print() {
	}
}

new Person().getPerson.print();
5.4.1 在构造器中调用构造器
public class Person {
	int a;
	Perosn() {
		this(10);  // 构造器调用置于起始位置不能调用两个
		// this("bbb");   // 不能调用两个构造器
	}
	Person(int a) {
		this.a = a;  // 参数名称和成员变量相同,使用this作为区分
		System.out.println("有参构造器");
	}
	Person(String b) {
	}
	void print() {
		// this(10);  // 除构造器之外,禁止在其他任何方法中调用构造器
	}
}
5.4.2 static方法

static方法就是没有this的方法。因此在static方法内部不能调用非静态方法,反过来可以。可以在没有创建任何对象的前提下,通过类来调用static方法。

5.5 终极处理和垃圾回收

一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize()方法。

public class Person {
	protected void finalize() {
		System.out.println("我被清理了");
	}
}

Person person = new Person();
person = null;  // 对象不会被引用
System.gc();    // 强制终止
垃圾回收器如何工作

Java从堆分配空间的速度,可以和其他语言从堆栈上分配空间的速度相媲美。

在某些Java虚拟机中,堆的实现更像是一个传送带,每分配一个对象,堆指针就往前移动一格。这意味着对象存储空间的分配空间很快。虽然薄记工作需要少量开销,但是没有查找可用空间的开销大。同时垃圾回收器对对象重新排列,实现了一种高速的、有无线空间可供分配的堆模型。

引用计数法:简单但速度很慢的垃圾回收技术,从未用于Java虚拟机的实现中
——每个对象含有一个引用计时器,当有引用连接时加1,当引用离开作用域或被置为null时减1。管理引用的开销不大,但是会在整个程序生命周期持续。垃圾回收器会遍历列表,释放引用数为0的对象空间。
——很难发现循环引用。

自适应:
从堆栈和静态存储区开始,遍历所有的引用。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复,直到根源于堆栈和静态存储区的引用所形成的网络全部被访问为止。这就解决了循环引用的问题。
处理存活对象:
(1)停止-复制
暂停程序的运行,将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。对象在复制到新堆时是一个挨着一个的。
缺点:需要修改堆栈的引用。还需要维护两个堆,在两个堆之间互相倒腾。可能产生的垃圾很少但仍然需要复制。
(2)标记-清扫
在寻找存活对象时给对象设一个标记。没有标记的对象不会被清理。所以剩下的堆空间是不连续的。

5.6 成员的初始化

对于方法的局部变量,程序员必须初始化,否则编译器会报错。
如果类的字段是基本类型,会有一个初始值,对象引用会是null。

初始化顺序

变量定义的先后顺序决定了初始化的顺序。即使变量定义散布在方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。先初始化静态对象,然后初始化非静态对象,然后调用构造方法。

静态初始化、非静态初始化
public class Person {
	static int a;
	static int b;
	static {
		a = 10;
		b = 20;
	}
	
	int c;
	int d;
	{
		c = 30;
		d = 40;
	}
}
5.8 数组初始化

数组只是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。数组通过方括号下标 *** 作符定义和使用。

int[] a1;   // 更常用,一个int类型数组
int a1[];
int[] a1 = { 1, 2, 3, 4 };  // 只能在数组被定义时使用
int[] a2;
a2 = new int[10];
int[] a3;
a3 = new int[] { 1, 2, 3, 4 };   
a1[0];
a1[a1.length-1];   // 数组的length成员
Arrays.toString(a1);
可变参数列表
public class  A {
	static void printArray(Object[] args) {
		for (Object obj : args) {
			System.out.println(args + " ");
		}
	}
	
	public static void main(String[] args) {
		printArray(new Object[] { new Integer(47), new String("aa") })
	} 
}
public class  A {
	static void printArray(Object... args) {
		for (Object obj : args) {
			System.out.println(args + " ");
		}
	}
	
	public static void main(String[] args) {
		printArray(new Integer(47), new String("aa"))
		printArray((Object[])new int[] { 1, 2 })
	} 
}
5.9 枚举类型
public enum A {
	NOT, MILD, HOT_HOT   // 实例是常量,使用大写
}
A.values() // 以声明顺序产生一个数组
a.ordinal() // 声明的顺序

由于switch是要在有限的集合中进行选择,因此它与enum正是绝佳的组合。

A a = A.NOT;
switch (a) {
	case NOT: 
		xxx;
		break;
	case MILD:
		xxx;
		break;
	default:
		xxx; 
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5697902.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存