目录
局部变量与成员变量
成员变量有默认值 (内存置零)
类型 默认值
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0
char '\u0000'
boolean false
String (or any object) null
局部变量没有默认值, 使用前必须要初始化
数组
数组是对象, 数组名是对数组对象的引用
数组一旦确定其大小是不能改变的, 数组比容器的效率高
== 操作符与 equal 方法
对于对象, == 比较的是引用
equals() 默认比较的是引用, 除非重写 equals()
for 逗号操作
Java 里唯一用到逗号操作符的地方就是 for 循环控制表达式, 要求是它们具有相同的类型.
for 循环的 3 部分中任意部分可以省略.
for ( ; ; ) 等价于 while (true)
标签
Java 里面没有 goto, 可以用标签结合 break / continue 实现 goto.
break / continue 默认中断的是当前循环, 若与标签一起使用, 可以中断标签处的循环.
注: 在 Java 中使用标签的唯一理由就是想跳出多层嵌套循环
枚举
枚举就是一个类, 与其他类没什么不同, 所有枚举都继承自抽象类 Enum.
枚举类型的实例是常量.
枚举序号从 0 开始.
枚举中可以定义实例变量, 实例方法, 静态方法.
枚举类可以声明抽象方法, 每个枚举值中可以实现该方法, 也可以重写其他方法.
枚举类可以实现接口.
异常
Throwable 是异常的根类, 可分为两类:
- Error -- 表示系统错误或资源耗尽, 由 Java 系统自己使用, 应用程序不应抛出和处理.
- Exception -- 可分为运行时异常和非运行时异常, 非运行时异常必须捕获或抛出.
在一个 catch 块中抛出异常, 会直接抛给上一级, 不会被同一个 try 块的后续 catch 子句捕获.
不要在 finally 块中使用 return 或抛出异常
try-with-resources 语法针对实现了 AutoCloseable 接口的类.
在 try() 内创建资源对象, 不能在 try() 内创建未实现 AutoCloseable 接口的对象.
在 try 块执行完后, 系统会自动调用资源的 close() 方法.
try(InputStream is = new FileInputStream(new File(""))) {
...
} catch (Exception e) {
...
}
泛型
泛型包括
- 泛型类
- 泛型接口
- 泛型方法 (与类或接口是否为泛型无关)
泛型擦除
泛型作用于静态类型检查期, 此后, 所有的泛型都被擦除, 替换为它们的非泛型上界.
泛型擦除使得任何在运行时需要知道确切类型信息的操作失效.
泛型的边界
extends 后面可以有至多一个类和多个接口, 如果有类, 类必须放在第一位, 后面跟接口
<? extends T>
不能用 add, 可以用 get.
如果 T 有两个子类 A 和 B, 不能确定到底是 A 还是 B, 不能把 B add 进 A, 所以不能 add; 但是不管是 A 还是 B, 都可以用 T 来接收, 所以可以 get.
<? super T>
不能用 get, 可以用 add.
如果 T 有两个父接口 A 和 B, 不能用 T 来接收它的父类, 所以不能 get; T 既是 A 又是 B, A 和 B 都可以接收 T, 所以可以 add.
继承与静态绑定
static 方法, final 方法, private 方法 (private 方法是隐式 final 的) 是静态绑定的, 其他所有方法都是后期绑定, 动态绑定, 运行期绑定.
父类的 private 方法不能被子类覆盖, 因为 private 是方法静态绑定的.
实例变量, 静态变量是静态绑定的.
输出 >>
father f
son g
father f
son g
默认方法继承问题
随着默认方法在 Java 8 中引入, 有可能出现一个类继承了多个方法而它们使用的却是同样的方法签名.
这种情况下, 如何确定使用哪一个方法?
反射
反射可以修改 final 和 private 修饰的字段.
特例, 反射不能修改 static final 修饰的基本类型字段 (即常量), 因为 Java 在编译时会把代码中常量的引用替换成具体的常量值.