关键字
# 2. 关键字
# final
final修饰的类无法继承
final修饰的方法无法覆盖
final的变量只能赋一次值
final修饰的引用一旦指向某个对象,则不能再重新指向其他对象,但该引用指向的对象内部的数据是可以修改的
final修饰的实例变量必须手动初始化,不能采用系统默认值
final修饰的实例变量一般和static联合使用,称为常量(常量名大写)
final的两个重排序规则 (opens new window)
# break、continue、return的区别
break 跳出总上一层循环,不再执行循环(结束当前的循环体) continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件) return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)
# instanceof 关键字的作用
instanceof
严格来说是 Java 中的一个双目运算符,用来测试一个对象是否为一个类的实例,通常在强制转换时先进行instanceof
判断。
Animal a = new Bird();
if(a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse();
}
2
3
4
5
注意:
- 编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
int i = 0;
System.out.println(i instanceof Integer);//编译不通过 i必须是引用类型,不能是基本类型
System.out.println(i instanceof Object);//编译不通过
2
3
- 在 JavaSE规范 中对 instanceof 运算符的规定就是:如果 obj 为 null,那么将返回 false。
System.out.println(null instanceof Object);
2
# static都有哪些用法?
静态变量和静态方法
也就是被static所修饰的变量/方法都属于类的静态资源,类实例所共享。
static静态块,多用于初始化操作
public calss PreCache{ static{ //执行相关操作 //初始化解析文件 } }
1
2
3
4
5
6用于修饰内部类,此时称之为静态内部类。
最后一种用法就是静态导包,即 import static
import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名,比如:
import static java.lang.Math.*; public class Test{ public static void main(String[] args){ //System.out.println(Math.sin(20));传统做法 System.out.println(sin(20)); } }
1
2
3
4
5
6
7
8
注:static修饰的静态变量以及静态代码块都是在类加载时执行,并且遵循自上而下的顺序依次逐行执行。
# volatile
Java 语言提供了一种稍弱的同步机制,即 volatile 变量,用来确保将变量的更新操作通知到其他线程。
volatile 变量具备两种特性,volatile 变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取 volatile 类型的变量时总会返回最新写入的值。
变量可见性
其一是保证该变量对所有线程可见,这里的可见性指的是当一个线程修改了变量的值,那么新的值对于其他线程是可以立即获取的。
禁止重排序
volatile 禁止了指令重排。
比 sychronized 更轻量级的同步锁
在访问 volatile 变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile 变量是一种比 sychronized 关键字更轻量级的同步机制。volatile 适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。
适用场景
值得说明的是对 volatile 变量的单次读/写操作可以保证原子性的,如 long和 double 类型变量,但是并不能保证 i++
这种操作的原子性,因为本质上 i++
是读、写两次操作。在某些场景下可以代替 Synchronized。但是,volatile 的不能完全取代 Synchronized 的位置,只有在一些特殊的场景下,才能适用volatile。总的来说,必须同时满足下面两个条件才能保证在并发环境的线程安全:
(1)对变量的写操作不依赖于当前值(比如 i++
),或者说是单纯的变量赋值(boolean flag = true)。
(2)该变量没有包含在具有其他变量的不变式中。也就是说,不同的 volatile 变量之间,不能互相依赖。只有在状态真正独立于程序内其他内容时才能使用 volatile 。