个人博客内容同步至公众号:第六范式
如有帮助欢迎关注,问题或建议,请公众号或博客留言。
Java中有些概念看似一字之差, 实则毫无联系。比如 final、finally 和 finalize ,Collection 和 Collections。如果你要问我final、finally 和 finalize有什么区别?Collection 和 Collections有什么区别?那我只能说不是雷锋和雷峰塔的区别就是美人和美人鱼的区别。
本文总结了Java面试中高频的几个容易混淆的概念解析,皆是干活,放心食用😄
- final、finally 和 finalize有什么区别?
- Collection 和 Collections有什么区别?
- 重写和重载有什么区别?
- String,StringBuffer和StringBuilder有什么区别?
- ArrayList和LinkedList有什么区别?
- throw和throws有什么区别?
- sleep()和wait()有什么区别?
1. final、finally 和 finalize有什么区别?
final
是 Java 中的关键字,它也是 Java 中很重要的一个关键字,final
修饰的类、方法、变量有不同的含义;finally
也是一个关键字,不过 finally 通常和其他关键字结合做一些组合操作;finalize
是一个不让人待见的方法,它是对象祖宗 Object 中的一个方法,finalize 机制现在已经不推荐使用了。
1.1 final的使用细节final
可以修饰类、属性、方法和局部变量.在某些情况下,程序员可能有以下需求,就会使用到 final
:
1) 当不希望类被继承时,可以用 final
修饰
2) 当不希望父类的某个方法被子类覆盖/重写 (override) 时,可以用 final
关键字修饰
3)当不希望类的的某个属性的值被修改,可以用 final
修饰.
4)当不希望某个局部变量被修改,可以使用 final
修饰
final 使用注意事项:
- final修饰的属性又叫常量,一般用 XX_XX_XX 来命名
- final修饰的属性,在定义时必须赋初值,并且以后不能再修改,赋值可以在如下位置之一:①定义时:如
public final double TAX_RATE = 0.08
;2)在构造器中;③在代码块中。
3)如果final修饰的属性是静态static的,则初始化的位置只能是定义时或在静态代码块(不能在构造器中赋值)。
4) final类不能继承,但是可以实例化对象。
5)如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。
5)一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。
6) final不能修饰构造方法(即构造器)
7) final和static往往搭配使用,效率更高,不会导致类加载(底层编译器做了优化处理)
8)包装类(Integer,Double,Float, Boolean等都是final),String也是final类。
9)final 修饰的引用类型,只是保证对象的引用不会改变。对象内部的数据可以改变。
1.2 finally的使用细节finally
是保证程序一定执行的机制,同样的它也是 Java 中的一个关键字,一般来讲,finally
一般不会单独使用,它一般和 try
块一起使用,例如下面是一段 try...finally
代码块:
1try{
2 lock.lock();
3}finally {
4 lock.unlock();
5}
这是一段加锁/解锁的代码示例,在 lock
加锁后,在 finally
中执行解锁操作,因为 finally
能够保证代码一定被执行,所以一般都会把一些比较重要的代码放在 finally
中,例如解锁操作、流关闭操作、连接释放操作等。
当 lock.lock()
产生异常时还可以和 try...catch...finally
一起使用:
1try{
2 lock.lock();
3}catch(Exception e){
4 e.printStackTrace();
5}finally {
6 lock.unlock();
7}
其次,finally
块在 try
块执行完成后,或者 try
块未执行完成但是接下来是控制转移语句时(return/continue/break),finally
块在控制转移语句之前执行
对于 finally
的执行时机,我们以 return 为例来看一下是怎么回事。如下这段代码:
1static int mayThrowException(){
2 try{
3 return 1;
4 }finally {
5 System.out.println("finally");
6 }
7}
8
9public static void main(String[] args) {
10 System.out.println(FinallyTest.mayThrowException());
11}
从执行结果可以证明是 finally 要先于 return 执行的。
当 finally 有返回值时,会直接返回。不会再去返回 try 或者 catch 中的返回值。
1static int mayThrowException(){
2 try{
3 return 1;
4 }finally {
5 return 2;
6 }
7}
8
9public static void main(String[] args) {
10 System.out.println(FinallyTest.mayThrowException());
11}
在执行 finally 语句之前,控制转移语句会将返回值存在本地变量中。
1static int mayThrowException(){
2 int i = 100;
3 try {
4 return i;
5 }finally {
6 ++i;
7 }
8}
9
10public static void main(String[] args) {
11 System.out.println(FinallyTest.mayThrowException());
12}
上面这段代码能够说明 return i
是先于 ++i
执行的,而且 return i
会把 i 的值暂存,和 finally
一起返回。
finally 的本质:
下面我们来看一段代码:
1public static void main(String[] args) {
2
3 int a1 = 0;
4 try {
5 a1 = 1;
6 }catch (Exception e){
7 a1 = 2;
8 }finally {
9 a1 = 3;
10 }
11
12 System.out.println(a1);
13}
这段代码输出的结果是什么呢? 答案是 3,Why??? (○´・д・)ノ
抱着疑问,我们先来看一下这段代码的字节码:
<