一、Math.round(11.5)等於多少?Math.round(-11.5)又等於多少?java
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11.四捨五入的原理是在參數上加0.5而後進行取整。面試
二、switch是否能做用在byte上,是否能做用在long上,是否能做用在String上?安全
Java5之前switch(expr)中,expr只能是byte、short、char、int。從Java5開始,Java引入了枚舉類型,expr也能夠是enum類型數據結構
從Java7開始,expr還能夠是字符串String,可是長整型(long)在目前全部的版本中都是不能夠的app
三、String、StringBuilder、StringBuffer的區別?工具
Java平臺提供了兩種類型的字符串:String和StringBuffer/StringBuilder,它們均可以儲存和操做字符串,區別以下。性能
1)String(最終類)是隻讀字符串,也就意味這String引用的字符串內容是不可改變的。初學者可能會有這樣的誤解:ui
String str = "abc";spa
str = "bcd";線程
如上、字符串str明明是能夠改變的呀,其實否則,str僅僅是一個引用對象,它指向一個字符串對象「abc」。第二行代碼的含義是讓str從新指向了一個新的字符串「bcd」對象,而「abc」對象並無任何改變,只不過該對象已經成爲了一個不可及對象(GC將要回收的對象)罷了。
2)StringBuilder/StringBuffer表示的字符串對象能夠直接進行修改。
3)StringBuilder是Java5引入的,它和StringBuffer的方法徹底相同,區別在於它是在單線程環境下使用的,由於它的全部方法都沒有被synchronized修飾,所以它的小輪理論上也要比StringBuffer要高。
四、什麼狀況下用「+」運算符進行字符串鏈接比調用StringBuilder/StringBuffer對象的append方法鏈接字符串性能更好?
字符串是Java程序最經常使用的數據結構之一。在Java中String類已經重載了「+」。也就是說,字符串能夠直接使用」+「進行鏈接,以下面代碼所示:
String s = "abc" + "def";
但這樣作真的好嗎?固然,這個問題不能簡單的回答yes or no 。要根據具體狀況來定。在Java中提供了一個StringBuilder類(Java5之後版本提供),這個類也能夠起到」+「的做用。那麼咱們應該用哪一個呢?
下面咱們先看看以下的代碼:
package string ;
public class TestSimplePlus{
public static void main(String[] args){
String s = "abc";
String ss = "ok" + s + "xyz" + 5;
System.out.println(ss);
}
}
上面的代碼將會輸出正確的結果。從表面看,對字符串和整型使用」+「並無什麼區別,但事實真的如此嗎?下面讓咱們開看看這段代碼的本質。
咱們首先使用反編譯工具(如 jdk 帶的 javap、或 jad)將 TestSimplePlus 反編譯成 Java Byte Code,其中的奧祕就一目瞭然了。在本文將使用 jad 來反編譯,命令以下:jad -o -a -s d.java TestSimplePlus.class
反編譯後的代碼以下:
讀者可能看到上面的 Java 字節碼感到迷糊,不過你們沒必要擔憂。本文的目的並非講解 Java Byte Code,所以,並不用瞭解具體的字節碼的含義。使用 jad 反編譯的好處之一就是能夠同時生成字節碼和源代碼。這樣能夠進行對照研究。從上面的代碼很容易看出,雖然在源程序中使用了"+",但在編譯時仍然將"+"轉換成 StringBuilder。所以,咱們能夠得出結論,在 Java 中不管使用何種方式進行字符串鏈接,實際上都使用的是 不管使用何種方式進行字符串鏈接,實際上都使用的是 StringBuilder 。那麼是否是能夠根據這個結論推出使用"+"和 StringBuilder 的效果是同樣的呢?這個要從兩個方面的解釋。若是從運行結果來解釋,那麼"+"和 StringBuilder 是徹底等效的。但若是從運行效率和資源消耗方面看,那它們將存在很大的區別。固然,若是鏈接字符串行表達式很簡單(如上面的順序結構),那麼"+"和 StringBuilder 基本是同樣的,但若是結構比較複雜,如使用循環來鏈接字符串,那麼產生的 Java Byte Code 就會有很大的區別。先讓咱們看看以下的代碼
你們能夠看到,雖然編譯器將「+」轉換成了StringBuilder,但建立StringBuilder對象的位置卻在for語句內部。這就意味着每執行一次循環,就會建立一個StringBuilder對象(對於本例來講,是建立了10個StringBuilder對象),雖然Java有垃圾回收器,但這個回收器的工做時間是不定的。若是不斷產生這樣的垃圾,那麼仍然會佔用大量的資源。解決這個問題的方法就是在程序中直接使用StringBuilder來鏈接字符串,代碼以下:
上面代碼反編譯後的結果以下所示:
從上面的反編譯結果能夠看出,建立StringBuilder的代碼被放在了for語句外。雖然這樣處理在源程序中看起來複雜,但卻換來了更好的效率,一樣的消耗的資源也更少了。
※4在使用StringBuilder時要注意,儘可能不要「+」和StringBuilder混着用,不然會建立更多的StringBuilder對象,以下面代碼所示:
改爲以下形式:
則反編譯後的結果以下:
從上面的代碼能夠看出,Java編譯器將「+」編譯成了StringBuilder,這樣for語句每循環一次,又建立了一個StringBuilder對象。
若是將上面的代碼在JDK1.4下編譯,必須將StringBuilder改成StringBuffer,而JDK1.4將「+」轉換爲StringBuffer。StringBuffer和StringBuilder的功能基本同樣,只是StringBuffer是線程安全的,而StringBuilder不是線程安全的。所以,StringBuilder的效率會更高。
六、請說出下面程序的輸出
補充:解答上面的面試題須要知道以下兩個知識點:
1)String對象的intern()方法會獲得字符串對象在常量池對應的版本中的引用(若是常量池中有一個字符串與String對象的equals結果是true),若是常量池中沒有對應的字符串,則該字符串被添加到常量池中,而後返回常量池中字符串的引用;
2)字符串的+操做其本質是建立了StringBuilder對象進行append操做,而後將拼接後的StringBuilder對象用toString方法處理成爲String對象,這一點能夠用javap -c StringEqualTest.class命令得到class文件對應的JVM字節碼指令就能夠看出來。