- 5.1 用构造器确保初始化
- 5.2 方法的重载
- 5.4 this关键字
- 5.4.1 在构造器中调用构造器
- 5.4.2 static方法
- 5.5 终极处理和垃圾回收
- 垃圾回收器如何工作
- 5.6 成员的初始化
- 初始化顺序
- 静态初始化、非静态初始化
- 5.8 数组初始化
- 可变参数列表
- 5.9 枚举类型
Java中构造器采用与类相同的名称,防止构造器与类中的方法名冲突,同时方便编译器自动调用。每个方法小写的编码风格不适用于构造器。
构造器没有返回值,这与返回值为空(void)是不同的。
Java默认提供无参构造器,也可以自己编写有参数的构造器。如果已经定义了 一个构造器,编译器就不会自动创建默认构造器。
5.2 方法的重载通过参数类型列表可以区分方法,参数的顺序不同也会用于区分。
根据方法的返回值来区分重载方法是行不通的。
如果你希望在方法的内部获得对当前对象的引用,由于这个引用是由编译器偷偷传进来的,所以没有标识符可用。可以使用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的对象空间。
——很难发现循环引用。
5.6 成员的初始化自适应:
从堆栈和静态存储区开始,遍历所有的引用。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复,直到根源于堆栈和静态存储区的引用所形成的网络全部被访问为止。这就解决了循环引用的问题。
处理存活对象:
(1)停止-复制
暂停程序的运行,将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。对象在复制到新堆时是一个挨着一个的。
缺点:需要修改堆栈的引用。还需要维护两个堆,在两个堆之间互相倒腾。可能产生的垃圾很少但仍然需要复制。
(2)标记-清扫
在寻找存活对象时给对象设一个标记。没有标记的对象不会被清理。所以剩下的堆空间是不连续的。
对于方法的局部变量,程序员必须初始化,否则编译器会报错。
如果类的字段是基本类型,会有一个初始值,对象引用会是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; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)