构造器
构造器采用与相同的名字,如果有了带入参的构造器(constructor),无入参的默认构造器使用前必须声明出来。
方法重载
为了让方法名相同而形式参数不同的方法同时存在——方法重载
区分重载的方法——每个重载的方法都必须有一个独一无二的参数类型列表
涉及基本类型的重载:
- 常数值被当做int处理
- char没有匹配(使用char的方法)直接上升至int
- 如果传入的数据类型小于方法声明的形式参数类型,实际数据类型会被提升
- 实参类型大于形参类型时,必须进行窄化转换,否则编译报错
另外!以返回值区分重载方法——行不通的
this关键字
写“this”时,都是指的“这个对象”或者“当前对象”,而且它本身表示对当前对象的引用。
如果给this添加参数列表来构造对象,则必须要放在构造器的最开始,且只能调用一次。
static的含义
static方法就是没有this的方法
static方法内部不可调用非静态方法
清理:终极处理和垃圾回收
finalize
每个对象在被垃圾回收时都会调用其finalize方法,但是我们不应该主动去调用这个方法来达成我们想要销毁某些对象的目的。这会因为:
- 对象可能不被垃圾回收
- 垃圾回收并不等于“析构”
- 垃圾回收只与内存有关
根据上述三条描述,在Java程序中,可以忘记这个关键字,不要使用它。
垃圾回收机制
垃圾回收器一面回收空间,一面使堆中的对象紧凑排列。
-
引用计数
- 简单,慢,对象含有一个引用计数器,在有引用连接到对象时+1,在引用离开作用域或者置为null时-1。
- 存在循环引用的问题,并未被任何一款虚拟机使用.
-
自适应回收 stop and copy
引用链,对任何“活对象”,一定能够最终追溯到器存活在堆栈或静态存储区之中的引用。
问题:效率低。- 需要维护两个堆
- 复制,系统稳定后垃圾少,仍会进行复制
为了解决第二个问题,在没有新垃圾时,进入mark-and-sweep模式,每次标记垃圾,然后对标记的垃圾进行处理,问题时速度慢,但是垃圾少的时候就会比较快。这是Sun早期的虚拟机垃圾回收机制。
-
分代技术
- 内存分为多个大块,用代数标记,处理大对象
- 只增加代数,不进行处理和复制。
成员初始化
Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量Java以编译错误的形式来贯彻这种,类的成员变量初始化则遵循以下规则。
8个基础类型:0, 0.0, false
对象引用:null
类的初始化
- 初始化顺序
变量定义的先后顺序决定了初始化顺序,但会在构造器前完成初始化。 - 静态数据的初始化
无论创建多少个对象,静态数据都只占用一份存储空间。- 静态初始化只有在必要时才会进行
- 初始化顺序是先静态对象,而后“非静态”对象
总结:- 构造器实际上也是静态方法
- 静态初始化只在class对象首次加载的时候进行一次
- new 对象时,首先在堆上为对象分配足够的存储空间
- 这块存储空间会被清空,成员变量赋值成0, 0.0或null
- 执行所有出现于字段定义处的初始化动作
- 执行构造器
- 显式的静态初始化——静态块
- 非静态实例初始化——{ }
除了没有static关键字,其他的和静态块表示一样。
数组初始化
声明:int[] a1 或 int a1[],这是一个引用,推荐使用前者,后者是C++的写法。
如果声明数组元素是非基本类型,那必须遍历初始化,否则会有空指针异常,P100,例子
用{1,2,3}来初始化
Integer[] a = {new Integer(1), new Integer(2)};
Integer[] b = new Integer[]{1,2};
Integer[] c = new Integer[2];
- 可变参数列表
形式:类型 … 形参名
这种形式在jdbc传入查询条件时很有用,但是也存在一些问题。之前做过一个项目需要处理不同制式的信号,每种信号存在不同数量的入参,为了让代码统一入口,我选择了这种可变参数列表来实现。这样做貌似还不错,所有的入口都用统一的方法进入,且没有重载多个方法。但是有个隐患,可变参数列表是允许参数列表个数为零的,所以当你忘记在入参中进行赋值时,这个参数列表会为null,如果你进行了判空,则后面代码逻辑走不到,没有判空则会抛出空指针异常,这个问题无法在代码编译时发现,只能通过测试发现,不符合在前端发现问题的初衷。
此外,如果一个方法使用了可变参数列表+固定参数的形式,则所有重载方法都需要声明一个非可变参数,否则虽然编译时不会报错,但是运行时会报“对f方法引用不明确”的错误
public class VariableArgumentLists {
static void f(float i, Character... args) {
System.out.println("first");
}
static void f(Character... args) {
System.out.println("second");
}
public static void main(String[] args) {
f(1, 'a');
f('a', 'b');
}
}
枚举类型
toString() 返回实际定义枚举名字符串
ordinal() 返回常量声明顺序,从0开始
valueOf() 通过枚举名取得对应的枚举实例
public class InitializationTest {
public static void main(String[] args) {
EnumClass enumClass = EnumClass.TEST_2;
System.out.println("enumClass.toString():" + enumClass.toString());
System.out.println("enumClass.ordinal():" + enumClass.ordinal());
System.out.println("EnumClass.TEST_1.ordinal():" + EnumClass.TEST_1.ordinal());
System.out.println("EnumClass.valueOf(\"TEST_1\"):" + EnumClass.valueOf("TEST_1"));
}
enum EnumClass {TEST_1, TEST_2}
}
输出:
enumClass.toString():TEST_2
enumClass.ordinal():1
EnumClass.TEST_1.ordinal():0
EnumClass.valueOf("TEST_1"):TEST_1