初始化和清理是影响代码安全的两个重要因素。
一、初始化
1. 方法重载
构造器与类名相同,成为强制重载方法名的原因之一。重载规则:每个重载的方法必须拥有独一无二的参数类型列表。不能根据返回值来区分重载方法。
Java基本类型的自动提升:byte(1) -> short/char(2) -> int(4) -> long(8) -> float(4) -> double(8byte)
假设有2个函数:print(char), print(int), 调用print('x')会执行第一个方法。
假设只有print(int), 调用print('x')时char会自动提升为int类型
假设只有print(char),使用高类型传参时需强制转换 print((char) 1)
2. this关键字
public class Leaf { int i; public Leaf(){ this(10); // 调用其他构造器 } public Leaf(int i){ this.i = i; // 表示数据成员 } public Leaf increment() { i++; return this; // 返回当前对象的引用 } public void print(){ System.out.println("i = " + i); } public static void main(String[] args) { new Leaf().increment().increment().print(); } }
static方法不存在this,因此静态方法不能调用非静态方法,无法传递调用对象。
3. 成员初始化
初始化值
方法的临时变量必须初始化,否则会编译失败。但类的成员变量会被赋予默认值如int=0,boolean=false,String=nul
数组的初始化可以使用可变参数列表,无需显示编写数组语法,编译器会自动填充数组。
public class Test { public static void main(String[] args) { print1(new String[]{"1", "2"}); print2("1", "2"); print2(); } public static void print1(String[] args){ System.out.println("print1: " + Arrays.toString(args)); } public static void print2(String...args){ // 当不传参时,容易与下面的无参函数混淆,虽然编译器不报错,但使用时最好注意是否与其他函数冲突 System.out.println("print2: " + Arrays.toString(args)); } public static void print2(){ System.out.println("print2 without params"); } }
初始化顺序
- 父类--静态变量
- 父类--静态初始化块
- 子类--静态变量
- 子类--静态初始化块
- 父类--变量
- 父类--初始化块
- 父类--构造器
- 子类--变量
- 子类--初始化块
- 子类--构造器
class Parent { public static String p_StaticField = "父类--静态变量"; public String p_Field = "父类--变量"; static { System.out.println(p_StaticField); System.out.println("父类--静态初始化块"); }
{ System.out.println(p_Field); System.out.println("父类--初始化块"); } public Parent() { System.out.println("父类--构造器"); } } public class SubClass extends Parent { public static String s_StaticField = "子类--静态变量"; public String s_Field = "子类--变量"; static { System.out.println(s_StaticField); System.out.println("子类--静态初始化块"); }
{ System.out.println(s_Field); System.out.println("子类--初始化块"); } public SubClass() { System.out.println("子类--构造器"); } public static void main(String[] args) { new SubClass(); } }
二、清理
使用垃圾回收器的唯一原因是为了回收程序不再使用的内存,但Java里的对象并非总是被垃圾回收,只要程序没有濒临存储空间用完,对象占用的空间就总也得不到释放。
finalize()方法的工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。