final,finally,finalize有什么区别?String, StringBuffer, StringBuilder有什么区别?Exception和Error有什么区别?

继上篇JVM学习以后,后面将分三期深刻介绍剩余JAVA基础面试题,每期3题。html

题目1、final,finally,finalize有什么区别?java

/*请尊重做者劳动成果,转载请标明原文连接:*/面试

/* https://www.cnblogs.com/jpcflyer/p/10739217.html* /编程

你们通常都这么回答:
final 能够用来修饰类、方法、变量,分别有不一样的意义,final 修饰的 class 表明不能够继承扩展,final 的变量是不能够修改的,而 final 的方法也是不能够重写的(override)。
finally 则是 Java 保证重点代码必定要被执行的一种机制。咱们可使用 try-finally 或者 try-catch-finally 来进行相似关闭 JDBC 链接、保证 unlock 锁等动做。
finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制如今已经不推荐使用,而且在 JDK 9 开始被标记为 deprecated。
 
从语法层次,这样说完是没有问题的,但让咱们深刻一下,何时会用到final?
若是你关注过 Java 核心类库的定义或源码, 有没有发现 java.lang 包下面的不少类,至关一部分都被声明成为 final class?在第三方类库的一些基础类中一样如此,这能够有效避免 API 使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。
使用 final 修饰参数或者变量,也能够清楚地避免意外赋值致使的编程错误,甚至,有人明确推荐将全部方法参数、本地变量、成员变量声明成 final。
final 变量产生了某种程度的不可变(immutable)的效果,因此,能够用于保护只读数据,尤为是在并发编程中,由于明确地不能再赋值 final 变量,有利于减小额外的同步开销,也能够省去一些防护性拷贝的必要。
另外,有一些常被考到的 finally 问题(也比较偏门),至少须要了解一下。好比,下面代码会输出什么?
1 try { 2   // do something
3   System.exit(1); 4 } finally{ 5   System.out.println(“Print from finally”); 6 }

上面 finally 里面的代码可不会被执行的哦,这是一个特例。数组

若是须要关闭链接等资源,推荐使用 Java 7 中添加的 try-with-resources 语句,由于一般 Java 平台可以更好地处理异常状况,编码量也要少不少,何乐而不为呢。
对于 finalize,咱们要明确它是不推荐使用的,业界实践一再证实它不是个好的办法,在 Java 9 中,甚至明确将 Object.finalize() 标记为 deprecated!若是没有特别的缘由,不要实现 finalize 方法,也不要期望利用它来进行资源回收。
为何呢?简单说,你没法保证 finalize 何时执行,执行的是否符合预期。使用不当会影响性能,致使程序死锁、挂起等。
 
题目2、String, StringBuffer, StringBuilder有什么区别?
接下来聊一聊平常使用的字符串,别看它彷佛简单,但实际上字符串涉及到的知识点特别多,在编程的大部分时候也都是在和字符串打交道。
通常回答:
 String 是 Java 语言很是基础和重要的类,提供了构造和管理字符串的各类基本逻辑。它是典型的 Immutable 类,被声明成为 final class,全部属性也都是 final 的。也因为它的不可变性,相似拼接、裁剪字符串等动做,都会产生新的 String 对象。因为字符串操做的广泛性,因此相关操做的效率每每对应用性能有明显影响。
StringBuffer 是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,咱们能够用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,因此除非有线程安全的须要,否则仍是推荐使用它的后继者,也就是 StringBuilder。
StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 没有本质区别,可是它去掉了线程安全的部分,有效减少了开销,是绝大部分状况下进行字符串拼接的首选。
 
再继续扩展一下:
首先看看 StringBuffer 实现的一些细节,它的 线程安全是经过把各类修改数据的方法都加上 synchronized 关键字实现的,很是直白。
为了实现修改字符序列的目的,StringBuffer 和 StringBuilder 底层都是利用可修改的(char,JDK 9 之后是 byte)数组,两者都继承了 AbstractStringBuilder,里面包含了基本操做,区别仅在于最终的方法是否加了 synchronized。
另外,这个内部数组应该建立成多大的呢?若是过小,拼接的时候可能要从新建立足够大的数组;若是太大,又会浪费空间。目前的实现是,构建时初始字符串长度加 16(这意味着,若是没有构建对象时输入最初的字符串,那么初始值就是 16)。咱们若是肯定拼接会发生很是屡次,并且大概是可预计的,那么就能够指定合适的大小,避免不少次扩容的开销。扩容会产生多重开销,由于要抛弃原有数组,建立新的(能够简单认为是倍数)数组,还要进行 arraycopy。
如对此感兴趣,能够继续阅读前文“ 深刻理解String, StringBuffer, StringBuilder的区别(基于JDK1.8)”

 

题目3、Exception和Error有什么区别?安全

直接看JAVA异常结构吧,JAVA异常的继承结构:Throwable为基类,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception。Error和RuntimeException及其子类成为未检查异常(unchecked),其它异常成为已检查异常(checked)。 

Error异常

Error表示程序在运行期间出现了十分严重、不可恢复的错误,在这种状况下应用程序只能停止运行,例如JAVA 虚拟机出现错误。Error是一种unchecked Exception,编译器不会检查Error是否被处理,在程序中不用捕获Error类型的异常。通常状况下,在程序中也不该该抛出Error类型的异常。

RuntimeException异常

Exception异常包括RuntimeException异常和其余非RuntimeException的异常。
RuntimeException 是一种Unchecked Exception,即表示编译器不会检查程序是否对RuntimeException做了处理,在程序中没必要捕获RuntimException类型的异常,也没必要在方法体声明抛出RuntimeException类。RuntimeException发生的时候,表示程序中出现了编程错误,因此应该找出错误修改程序,而不是去捕获RuntimeException。

Checked Exception异常

Checked Exception异常,这也是在编程中使用最多的Exception,全部继承自Exception而且不是RuntimeException的异常都是checked Exception,上图中的IOException和ClassNotFoundException。JAVA 语言规定必须对checked Exception做处理,编译器会对此做检查,要么在方法体中声明抛出checked Exception,要么使用catch语句捕获checked Exception进行处理,否则不能经过编译。