Java 面试常考关键字
前言:在上次面试的时候答了几个关键字,感觉答得不是很好,虽然点都答到了,但是话语说出来不是那么利索,索性还是来整理一下吧。
final
final是Java 面试中经常考到的一个关键字,因为使用在不同的地方,final的含义也是不同的。
1、final 变量。如果用final 修饰一个基本数据类型的变量的话,其数据一旦在初始化后变不能更改;如果是引用类型的变量的话,在对其初始化后则不能让其再指向另一个对象,而其引用的对象本身还是可以变的。例如:创建一个StringBuffer的对象,用final修饰,还可以使用append方法修改对象本身,但是指向的对象并没有改变,还是这个StringBuffer对象。
2、final 方法。如果在方法前面加final 关键字,则表示该方法不能被子类重写。使用final 修饰方法的原因有两个:一是将方法锁定,防止其子类重写,二是提高效率,final 方法比非final 方法要快。
3、final 类。使用final 修饰的类叫final 类。final 类的功能通常比较完整,因而不能被继承。例如:
(1)包装类。Boolean、Character、Short、Integer、Long、Float、Double、Byte、Void
(2)字符串类。String、StringBuffer、StringBuilder
(3)系统类。Class、System、RuntimePermission、Compiler
(4)数学类。Math、StrictMath
等等。
关于final 的重要知识点
1、final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
2、在匿名类中所有变量都必须是final变量。
3、final关键字不同于finally关键字,后者用于异常处理。
4、final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
5、接口中声明的所有变量本身是final的
6、final方法在编译阶段绑定,称为静态绑定(static binding)
7、没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
8、将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
volatile
volatile 主要有两层语义
1、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对于其它线程来说是立即可见的。但不能保证原子性(例如自加操作,需要加锁才能保证原子性)。
2、禁止指令重排序。(面试时忘了,要好好记一记)
synchronized
在Java 中,每一个对象都有且仅有一个同步锁,即同步锁依赖对象而存在。当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。不同线程对同步锁的访问是互斥的。synchronized 有以下三条原则:
1、当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
2、当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
3、当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
synchronized 有synchronized 方法和synchronized 代码块。例如
// synchronized 方法
public synchronized void foo1() { System.out.println("synchronized methoed"); }
//synchronized 代码块
public void foo2() { synchronized (this) { System.out.println("synchronized methoed"); } }
关于实例锁和全局锁
实例锁:锁在某一个实例对象上,对应synchronized 关键字
全局锁:锁针对的是类,无论实例多少个对象,线程将共享该锁,对应synchronized static 关键字
static
1、static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。
简而言之:就是在没有创建对象的情况下也能调用,通过类名就可以访问。没有this。
static 方法一般称作静态方法。静态方法是不能访问类的非静态成员变量和非静态成员方法,但是非静态成员方法中是可以访问静态成员方法和变量的。
2、static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。
3、static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。