1.Java 8 的重要特性有哪些?
2014年3月發(fā)布的Java8,是Java面試中熱門的問(wèn)題之一。如果你回答的清晰,表明你對(duì)Java最新技術(shù)是與時(shí)俱進(jìn)。
Java8是自Java5注解和泛型功能以來(lái)變化最大的版本。一些重要的特性諸如:
1. Interface changes with default and static methods
2. Functional interfaces and Lambda Expressions
3. Java Stream API for collection classes
強(qiáng)烈推薦訪問(wèn)以上鏈接了解每個(gè)具體的細(xì)節(jié),或者閱讀Java 8 Features。
2.Java的跨平臺(tái)特性指的什么?
跨平臺(tái)意味著你能在任何操作系統(tǒng)運(yùn)行同樣的Java程序。例如,你可以將在Windows平臺(tái)寫的Java程序放到Max OS系統(tǒng)運(yùn)行。
3.什么是JVM?它可以跨平臺(tái)否?
Java虛擬機(jī)是Java程序語(yǔ)言的核心。JVM負(fù)責(zé)將字節(jié)碼機(jī)器可讀的代碼。JVM是非跨平臺(tái)的,這也就是你需要在不同的操作系統(tǒng)上安裝不同的JVM。我們也可以定制JVM配置,比如設(shè)置最小和最大分配內(nèi)存。它是虛擬的,而且不受底層操作系統(tǒng)依賴。
4.JDK和JVM有什么區(qū)別?
Java開(kāi)發(fā)套件(JDK)的目的是為開(kāi)發(fā)服務(wù)的,JVM是其中一部分,它旨在運(yùn)行Java程序。JDK提供所有的開(kāi)發(fā)工具,需要編譯的可執(zhí)行二進(jìn)制文件,調(diào)試和執(zhí)行Java應(yīng)用程序。可執(zhí)行部分由JVM處理,來(lái)提供機(jī)器獨(dú)立運(yùn)行。
5.JVM和JRE有什么區(qū)別?
Java運(yùn)行時(shí)環(huán)境(JRE)是JVM的具體實(shí)現(xiàn)。JRE由JVM和Java二進(jìn)制還有其他classes類組成,以保證正確執(zhí)行Java程序。JRE不包含任何開(kāi)發(fā)工具,比如Java編譯器,測(cè)試工具等。如果你要執(zhí)行任何Java程序,你必須安裝JRE。
6.Java中所有類的父類是什么?
java.lang.Object是所有Java類的父類,使用的時(shí)候不需要繼承它。
7.為什么Java不支持多繼承?
Java不支持類的多繼承是因?yàn)榇嬖凇般@石問(wèn)題”。了解“鉆石問(wèn)題”的例子可以查看文章Multiple Inheritance in Java。
然后多繼承關(guān)系可以通過(guò)接口來(lái)實(shí)現(xiàn)。一個(gè)接口可以繼承多個(gè)接口,因?yàn)樗麄冎宦暶髁朔椒?,而具體的實(shí)現(xiàn)放在實(shí)現(xiàn)類里面,所以接口中不會(huì)存在“鉆石問(wèn)題”。
8.為什么Java不是純面向?qū)ο笳Z(yǔ)言?
因?yàn)镴ava原始類型,例如:int,byte,short,long等,所以Java不是純面向?qū)ο笳Z(yǔ)言。我認(rèn)為它給我們?cè)诰帉懘a時(shí)提供了便捷。
顯然Java可以用封裝對(duì)象給原始對(duì)象提供展示,但他們沒(méi)有任何好處。
眾所周知,所有的原始對(duì)象都有封裝對(duì)象,例如:Integer,Long等,封裝對(duì)象中會(huì)有額外的一些方法。
9.path和classpath變量有什么區(qū)別?
PATH是操作系統(tǒng)使用的環(huán)境變量,用于放置執(zhí)行相關(guān)的文件。這就是為什么我們安裝完Java,想讓操作系統(tǒng)找到執(zhí)行文件,我們需要把Java目錄位置加到PATH環(huán)境變量中。
Classpath是Java特定用的,用于Java執(zhí)行文件放置class文件。我們可以在Java應(yīng)用運(yùn)行時(shí)提供classpath路徑,可以是個(gè)目錄,ZIP文件,JAR文件等。
10.Java中main方法有什么重要性?
main()方法是任何獨(dú)立Java應(yīng)用的入口。main方法的語(yǔ)法如下:
public static void main(String args[])
main方法是public和static修飾的,所以Java不用初始化類就能夠訪問(wèn)它。方法參數(shù)是String數(shù)組,我們可以在運(yùn)行程序時(shí)候傳進(jìn)來(lái),查看這篇文章可以進(jìn)一步了解how to compile and run java program。
11.Java中方法重載和方法重寫有什么區(qū)別?
當(dāng)我們?cè)谝粋€(gè)class類中想使用同一個(gè)方法名稱實(shí)現(xiàn)多個(gè)方法而且參數(shù)不同時(shí),這時(shí)候就可以用方法重載。
方法重寫的概念來(lái)自于繼承的情況,當(dāng)我們有兩個(gè)方法用了同一個(gè)方法簽名,一個(gè)是在父類,另一個(gè)是在子類。我們可以在子類中使用@Override注解重寫方法實(shí)現(xiàn),這樣可以確保父類中方法改變了,子類中也跟著變。
重載體現(xiàn)的類內(nèi)部的多態(tài)性,重寫體現(xiàn)的是父、子類繼承間的多態(tài)性。
12.是否可以重載main方法?
是的,我們可以在同一個(gè)class類中寫多個(gè)名稱是"main"的方法。然后當(dāng)Java虛擬機(jī)運(yùn)行時(shí)候會(huì)根據(jù)public static void main(String args[])語(yǔ)法來(lái)找對(duì)應(yīng)的main方法。
13.是否可以在Java源文件中寫多個(gè)public classes?
Java不允許在一個(gè)源文件中寫多個(gè)public class。一個(gè)源文件可以含有多個(gè)非public聲明的class。
14.什么是Java的Package,哪些包是默認(rèn)引入的?
包是Java中有效組織類分組的機(jī)制。分組邏輯可以基于設(shè)計(jì)的功能也可以基于模塊。完全區(qū)分一個(gè)Java類包括包路徑和類名稱。例如java.lang.Object,完全區(qū)分是由類名稱Object加上包路徑j(luò)ava.lang。
java.lang下的包是默認(rèn)引入的,所以我們的程序里面無(wú)需引入該包下的類。
15.什么Java訪問(wèn)修飾符
Java通過(guò)public, private and protected訪問(wèn)修飾詞提供訪問(wèn)控制。當(dāng)沒(méi)有任何修飾詞時(shí),屬于默認(rèn)訪問(wèn)修飾。
Java類只能包含public或者默認(rèn)修飾詞。閱讀Java Access Modifiers了解更多細(xì)節(jié)。
16.什么是final關(guān)鍵字?
類上使用final關(guān)鍵詞修飾為了確保沒(méi)有其他類可以繼承它,例如String類是final修飾,所以我們無(wú)法繼承String。
方法上使用final關(guān)鍵詞修飾為了確保子類無(wú)法重寫該方法。
變量上使用final關(guān)鍵詞修飾為了確保其只能分配一次。然后變量的狀態(tài)可以改變,例如可以給一個(gè)object分配final變量,但是object變量后面還可以修改。
17.什么是static關(guān)鍵字?
static關(guān)鍵詞可以修飾class 層級(jí)的變量,使其變成全局共享變量。
static關(guān)鍵詞也可以修飾方法。靜態(tài)方法只能訪問(wèn)靜態(tài)變量,同時(shí)也只能調(diào)用類的靜態(tài)方法。
閱讀java static keyword了解更多。
18.Java中finally和finalize的區(qū)別?
finally代碼塊用在try-catch中,用以確保改部分代碼始終會(huì)執(zhí)行,即便是任何異常拋出的情況。
finally代碼塊經(jīng)常用來(lái)處理try代碼塊中創(chuàng)建的資源進(jìn)行回收。
finalize()是Object類中特定的方法,可以在基礎(chǔ)的類中進(jìn)行重寫。當(dāng)object準(zhǔn)備垃圾回收時(shí),這個(gè)方法會(huì)被垃圾回收調(diào)用。這個(gè)方法經(jīng)常重寫用于在垃圾回收時(shí)釋放系統(tǒng)資源。
19.是否可以聲明一個(gè)靜態(tài)類?
不能聲明頂層類為靜態(tài)類,然后一個(gè)內(nèi)部類可以聲明成靜態(tài)static。如果內(nèi)部類被聲明為靜態(tài)類,它被叫做靜態(tài)嵌套類。內(nèi)部靜態(tài)類和其他頂層類是一樣的,嵌套只是為了打包方便。
閱讀java inner class了解更多。
20.什么是靜態(tài)引用?
如果我們使用其他類中的靜態(tài)變量或靜態(tài)方法,通常我們先引入該類,然后使用該類的方法/變量。
import java.lang.Math;
//inside class?
double test = Math.PI * 5;
當(dāng)只需要用某個(gè)方法或變量時(shí),我們也可以同樣的引入靜態(tài)方法或變量
import static java.lang.Math.PI;
//no need to refer class now
double test = PI * 5;
使用靜態(tài)引入會(huì)產(chǎn)生混淆,所以需要盡量避免這種方式。過(guò)渡使用靜態(tài)引用會(huì)導(dǎo)致你的程序可讀性差和可維護(hù)性低。
21.什么是try-with-resources?
Java7的一個(gè)特性是try-with-resources聲明,用于動(dòng)態(tài)資源管理。Java7之前沒(méi)有動(dòng)態(tài)資源管理,我們需要明確需要關(guān)閉的資源。通常會(huì)在try-catch聲明的finally代碼塊中實(shí)現(xiàn)。當(dāng)我們忘記關(guān)閉資源時(shí)這種方法會(huì)導(dǎo)致內(nèi)存不足。
從Java7開(kāi)始,我們可以在try代碼塊中創(chuàng)建資源和使用它,當(dāng)try-catch代碼塊結(jié)束時(shí),Java會(huì)馬上處理好資源的。閱讀Java Automatic Resource Management了解更多。

22.什么是multi-catch塊?
多個(gè)異常塊捕獲代碼是Java7的一個(gè)改善,我們可以捕獲多個(gè)異常在同一個(gè)catch塊中。當(dāng)每一個(gè)catch塊中都是相似代碼的時(shí)候,這樣的處理會(huì)讓代碼變得簡(jiǎn)潔。
如果一個(gè)catch塊處理多個(gè)異常,可以使用管道符"|",這種情況下異常參數(shù)是final修飾,所以無(wú)法改變它。閱讀Java multi catch block了解更多。
23.什么是靜態(tài)塊?
Java靜態(tài)代碼塊是通過(guò)Java ClassLoader把類加載到內(nèi)存時(shí)候的一組可執(zhí)行的聲明。它被用來(lái)初始化類中的靜態(tài)變量。大多數(shù)情況當(dāng)類加載時(shí)創(chuàng)建靜態(tài)資源。
24.什么是接口?
接口是Java程序語(yǔ)言的核心部分,不僅廣泛用于JDK,而且在Java設(shè)計(jì)模式中,大多數(shù)框架中,工具類中都有使用。接口給Java提供了一種抽象化的途徑,而且用于約定在子類中的實(shí)現(xiàn)。
接口有利于定義類型和在我們代碼里創(chuàng)建集成關(guān)系的頂層邏輯。由于Java類可以實(shí)現(xiàn)接口的多繼承,所以在大多數(shù)情況下最好使用超類當(dāng)接口。閱讀java interface了解更多。
25.什么是抽象類?
抽象類用在Java中為子類們創(chuàng)建一個(gè)超類且含有具體的方法實(shí)現(xiàn)。一個(gè)抽象類可以有不含方法體的抽象方法,也可以有具體實(shí)現(xiàn)的抽象方法。
abstract關(guān)鍵字用于創(chuàng)建抽象類。抽象類不能被實(shí)例化,通常用在提供子類繼承和實(shí)現(xiàn)基礎(chǔ)的抽象方法和重寫或者用抽象類中的方法。閱讀java abstract class了解更多。
26.Java中抽象類和接口的區(qū)別?
abstract關(guān)鍵詞創(chuàng)建抽象類而interface關(guān)鍵詞創(chuàng)建的是接口;
抽象類可以有具體的方法實(shí)現(xiàn)而接口沒(méi)有;
一個(gè)類只能繼承一個(gè)抽象類,但是可以實(shí)現(xiàn)多個(gè)接口;
我們可以運(yùn)行含有main()方法的抽象類,而接口不行;
27.接口是否可以實(shí)現(xiàn)或繼承另一個(gè)接口?
接口無(wú)法實(shí)現(xiàn)另一個(gè)接口,他們是繼承關(guān)系。因?yàn)榻涌跊](méi)有方法實(shí)現(xiàn),所以不存在“diamond”問(wèn)題,這就是為什么會(huì)允許多接口繼承,一個(gè)接口也可以繼承多個(gè)接口。
28.什么是Marker interface?
Java中Marker interface是指一個(gè)空的接口沒(méi)有任何方法,但在一些功能設(shè)計(jì)的類里面強(qiáng)制實(shí)現(xiàn)。我們熟知的一些marker interfaces例如Serializable、Cloneable。
29.什么是Wrapper classes?
Java的嵌套類是Object對(duì)八種原始類型的展示。Java中所有嵌套類都是不可變和final修飾的。Java5中自動(dòng)裝箱和拆箱允許一種便捷的方式轉(zhuǎn)換原始類型和它們對(duì)應(yīng)的封裝類型。
閱讀Wrapper classes in Java了解更多。
30.什么是Java中的枚舉?
枚舉是Java1.5中引入的新類型,它的filed是固定的常量Set集合。例如我們可以創(chuàng)建方向的枚舉集合:東、西、南、北。
同類類似,創(chuàng)建枚舉的關(guān)鍵詞是enum。枚舉常量是隱形的靜態(tài)和final。
閱讀java enum了解更多。
31.什么是Java注解?
Java注解提供關(guān)于代碼的信息,它們對(duì)注解的代碼塊沒(méi)有直接影響。注解是Java5引入的。注解是嵌入在程序中關(guān)于程序的元數(shù)據(jù)。注解的語(yǔ)法解析可以被注解解析工具或者編譯器解析。我們也可以指定注解是編譯時(shí)有效或運(yùn)行時(shí)有效。Java內(nèi)置的注解有@Override, @Deprecated,@SuppressWarnings。
閱讀java annotations了解更多。
32.什么是Java反射API?為何它非常重要?
Java反射API是檢查和修改Java應(yīng)用運(yùn)行時(shí)行為的一種方式。我們可以檢查類、接口、枚舉,獲取它們的方法和成員變量的細(xì)節(jié)。反射API是高級(jí)技能,我們應(yīng)該避免在平時(shí)編碼時(shí)使用。反射API的用法可以打破設(shè)計(jì)模式,比如單例模式,通過(guò)調(diào)用私有構(gòu)造器等可以違反Java里訪問(wèn)修飾的規(guī)則。
即便我們不在普通應(yīng)用編碼時(shí)使用反射API,但它還是有其重要意義。在一些框架中,比如Spring,Hibernate或容器應(yīng)用例如Tomcat,Jobss里不能沒(méi)有反射API。它們通過(guò)反射API調(diào)用合適的方法和實(shí)例化對(duì)象,在其他程序處理中也應(yīng)用廣泛。
閱讀Java Reflection Tutorial深入了解反射API。
33.什么是Java復(fù)合Composition?
復(fù)合/組合是Java類中實(shí)現(xiàn)has-a關(guān)系的設(shè)計(jì)技術(shù),我們可以使用對(duì)象組合來(lái)實(shí)現(xiàn)代碼重用。
我們可以針對(duì)其他的對(duì)象實(shí)例化成變量來(lái)實(shí)現(xiàn)Java組合,其好處是我們可以控制類中其他對(duì)象的可見(jiàn)性,在我們需要的時(shí)候重用。
閱讀Java Composition了解復(fù)合/組合示例。
34.復(fù)合優(yōu)于繼承的好處有哪些?
Java程序中最佳實(shí)踐之一是“復(fù)合優(yōu)于繼承”原則,一些原因如下:
a.任何父類的變化可能都會(huì)影響子類,及時(shí)我們不會(huì)用到的父類方法。例如,我們?cè)谧宇愔杏幸粋€(gè)test()方法,突然有人在其父類也寫了個(gè)test()方法,會(huì)導(dǎo)致子類編譯錯(cuò)誤。復(fù)合就絕不會(huì)有這種問(wèn)題,因?yàn)槲覀冎皇褂梦覀冃枰姆椒ā?/p>
b.繼承暴露了所有父類的方法和變量給繼承者們,如果我們掌握不好父類的設(shè)計(jì),會(huì)導(dǎo)致安全漏洞。復(fù)合允許我們提供嚴(yán)格的方法訪問(wèn),因此更加安全。
c.我們可以在運(yùn)行時(shí)進(jìn)行復(fù)合綁定,然后繼承綁定需要在編譯時(shí)期。這樣復(fù)合提供更加靈活的方法調(diào)用。
閱讀java composition vs inheritance了解更多組合優(yōu)于繼承的好處。
35.如何對(duì)customer對(duì)象集合排序?
需要實(shí)現(xiàn)Comparable接口來(lái)支持customer集合的排序。Comparable接口有compareTo(T obj)方法,用來(lái)做排序的方法,也提供了它的實(shí)現(xiàn)。我們可以使用默認(rèn)的方式來(lái)對(duì)集合中customer對(duì)象來(lái)排序。
36.什么是Java中內(nèi)部類?
我們可以在類的內(nèi)部定義一個(gè)類,叫做嵌套類。任何非靜態(tài)嵌套類叫內(nèi)部類。內(nèi)部類和類對(duì)象關(guān)聯(lián),它可以訪問(wèn)外層類的所有變量和方法。由于內(nèi)部類和實(shí)例有關(guān)聯(lián),所以不能含有靜態(tài)變量。我們可以有局部?jī)?nèi)部類或匿名內(nèi)部類。
閱讀java inner class了解更多。
37.什么是匿名內(nèi)部類?
局部?jī)?nèi)部類如果沒(méi)有名稱,就是匿名內(nèi)部類。一個(gè)匿名類的定義和實(shí)例化都是一條聲明。匿名內(nèi)部類通常繼承一個(gè)類或者實(shí)現(xiàn)一個(gè)接口。
由于匿名內(nèi)部類沒(méi)有名字,所以無(wú)法定義構(gòu)造方法。匿名內(nèi)部類可訪問(wèn)域是它的定義位置。
38.什么是Classloader?
Java?Classloader是一個(gè)我們需要訪問(wèn)類時(shí)加載程序字節(jié)碼到內(nèi)存的程序。我們也可以擴(kuò)展Classloader類,重寫loadClass(String name)方法來(lái)創(chuàng)建自己的classloader。
閱讀java classloader了解更多。
39.有哪些不同類型的Classloader?
Java中內(nèi)置了三種類型類加載器:
1.Bootstrap Class Loader –?它加載JDK的內(nèi)部類,典型的有rt.jar和其他核心類;
2.Extensions Class Loader – 它加載JDK擴(kuò)展目錄的類,通常是$JAVA_HOME/lib/ext目錄;
3.System Class Loader – 它加載當(dāng)前classpath的類,可以在調(diào)用程序是命令行指定-cp或者-classpath命令來(lái)設(shè)置。

40.什么是三元運(yùn)算符?
Java條件運(yùn)算符僅指的條件運(yùn)算,例如三元運(yùn)算。它在Java程序應(yīng)用廣泛,是內(nèi)部替代if-then-else語(yǔ)句用的。我們可以用條件運(yùn)算符 if-else語(yǔ)句或者switch條件。
閱讀java ternary operator了解更多。
41.super關(guān)鍵字有什么作用?
super關(guān)鍵字可以用來(lái)訪問(wèn)父類的方法,當(dāng)你在子類重寫了該方法時(shí)用的。
我們可以在子類構(gòu)造器通過(guò)super關(guān)鍵字調(diào)用父類構(gòu)造器但是這種情況需要將第一條聲明寫在構(gòu)造器方法里。
package com.journaldev.access;
public class SuperClass {
????????public SuperClass(){
?????????}????????public SuperClass(int i){}
????????public void test(){
?????????????System.out.println("super class test method");
?????????}?}
使用super關(guān)鍵字的例子可以參考下面子類的實(shí)現(xiàn):
package com.journaldev.access;
public class ChildClass extends SuperClass {
? ?????? public ChildClass(String str){
? ?????????? //access super class constructor with super keyword
? ?????????? super();
? ?????????? //access child class method
? ?????????? test();
? ?????????? //use super to access super class method
? ?????????? super.test();
? ? ? ? }
? ?????? @Override????
? ?????? public void test(){
? ?????????? System.out.println("child class test method"); }
? ? ? ? }
}
42.說(shuō)明下break和continue聲明的用途?
我們可以使用break語(yǔ)句終止for,while,或者do-while循環(huán)??梢栽趕witch語(yǔ)句中退出switch條件。你可以看下break的例子java break。我們可以使用break當(dāng)作標(biāo)簽來(lái)退出內(nèi)部循環(huán)。
continue語(yǔ)句是在for,while或者do-while循環(huán)中跳過(guò)當(dāng)次循環(huán)。我們可以使用continue語(yǔ)句當(dāng)作標(biāo)簽來(lái)跳過(guò)當(dāng)次循環(huán)。
43.this關(guān)鍵字有什么用?
this關(guān)鍵字提供了當(dāng)前類的引用,它常用來(lái)確保一個(gè)類里面的變量是被調(diào)用,而不是局部同名變量被調(diào)用了。
44.什么是默認(rèn)構(gòu)造器?
類的無(wú)參構(gòu)造函數(shù)就是默認(rèn)的構(gòu)造函數(shù)。當(dāng)我們沒(méi)有寫無(wú)參類,Java編譯器會(huì)自動(dòng)給類創(chuàng)建一個(gè)默認(rèn)的無(wú)參構(gòu)造器。如果有其他的構(gòu)造器定義了的話,編譯器就不會(huì)創(chuàng)建默認(rèn)的了。
45.是否可以在try中不寫catch代碼塊?
可以,我們可以寫try-finally語(yǔ)句而沒(méi)有catch代碼塊。
46.什么是垃圾回收?
垃圾回收是在堆內(nèi)存中回收沒(méi)有被使用的對(duì)象的進(jìn)程。在Java中,分配內(nèi)存的過(guò)程是自動(dòng)由garbage collector處理的。
我們可以在代碼中寫Runtime.getRuntime().gc()來(lái)運(yùn)行垃圾回收,或者使用System.gc()。查看更多分析堆內(nèi)存和垃圾回收機(jī)制的,閱讀Java Garbage Collection。
47.什么是序列化和反序列化?
我們把Java對(duì)象轉(zhuǎn)換成流的過(guò)程叫做序列化。一旦Java對(duì)象被轉(zhuǎn)換成流,它就能被保存到文件或者發(fā)送到網(wǎng)絡(luò)傳輸或者用到socket連接中。
對(duì)象在實(shí)現(xiàn)序列化接口后,我們可以用java.io.ObjectOutputStream來(lái)講對(duì)象寫到文件或者任何OutputStream對(duì)象中。閱讀Java Serialization了解更多。
進(jìn)程通過(guò)序列化將流數(shù)據(jù)轉(zhuǎn)換成對(duì)象的過(guò)程叫反序列化。閱讀Java Deserialization了解更多。
48.如何在cmd窗口運(yùn)行JAR文件
我們?nèi)绻诿钚羞\(yùn)行JAR文件,它需要有mainfest文件定義Main-Class入口。Main-Class是JAR文件的入口,命令行運(yùn)行時(shí)需要用到。
49.System類有哪些用途?
Java的System類是核心類之一,調(diào)試時(shí)候最早記錄日志信息就是通過(guò)System.out.print()方法來(lái)實(shí)現(xiàn)的。
System類是final的,所以它不能有子類,也不能通過(guò)繼承來(lái)重寫。System類不提供任何公共構(gòu)造器,所以我們無(wú)法實(shí)例化這個(gè)類,這就是為什么它所有的方法都是靜態(tài)方法。
System的一些有用的方法有數(shù)組復(fù)制,獲取當(dāng)前系統(tǒng)時(shí)間,讀取系統(tǒng)環(huán)境變量等。
閱讀Java System Class了解更多。
50.instanceof關(guān)鍵字有什么作用?
instanceof關(guān)鍵字用來(lái)檢查一個(gè)對(duì)象是否是某個(gè)類的類型。我們贏盡可能避免使用它。用法示例:
public static void main(String args[]){
? ?????? Object str = new String("abc");
? ?????? if(str instanceof String){
? ?????????? System.out.println("String value:"+str);
? ? ? ? }
? ?????? if(str instanceof Integer){
? ?????????? System.out.println("Integer value:"+str);
? ? ? ? }
}
由于str在運(yùn)行時(shí)是String類型,第一個(gè)if語(yǔ)句計(jì)算的值是true而第二個(gè)計(jì)算值是false。
51.switch case中是否可以用String?
Java7的一個(gè)特性是改進(jìn)了switch case允許使用String。所以如果使用Java7或者更高版本,你可以在switch-case語(yǔ)句中使用String。
閱讀Java switch-case String example了解更多。
52.Java是值傳遞還是引用傳遞?
這是個(gè)容易混淆的問(wèn)題,我們知道對(duì)象變量包含對(duì)象到堆的引用。當(dāng)我們調(diào)用任何方法時(shí),這些變量被傳遞而且存儲(chǔ)在方法棧內(nèi)存中。我們可以通過(guò)簡(jiǎn)單的方法交換對(duì)所有語(yǔ)言測(cè)試到底是引用傳遞還是值傳遞,了解更多請(qǐng)閱讀Java is Pass by Value and Not Pass by Reference。
53.堆和棧內(nèi)存的區(qū)別?
以下是堆和棧內(nèi)存的主要區(qū)別:
?堆內(nèi)存被應(yīng)用所有部分使用而棧內(nèi)存只被一個(gè)線程執(zhí)行時(shí)使用;
?無(wú)論一個(gè)對(duì)象是否創(chuàng)建,它總是存儲(chǔ)在堆內(nèi)存棧內(nèi)存包含它的引用。棧內(nèi)存包含局部原始變量,對(duì)象的引用變量在堆內(nèi)存區(qū)。
?棧內(nèi)存管理由LIFO管理完成,然而堆內(nèi)存管理則更加復(fù)雜,因?yàn)樗侨值摹?/p>
通過(guò)一個(gè)簡(jiǎn)單的程序了解更多細(xì)節(jié),閱讀Java Heap vs Stack Memory。
54.Java編譯的文件存在JDK,JRE還是JVM?
Java編譯器的任務(wù)是將程序轉(zhuǎn)換為字節(jié)碼,我們有javac來(lái)執(zhí)行編譯。所以它一定存在于JDK,我們?cè)贘RE不需要而JVM只是規(guī)范。
55.下面的程序輸出結(jié)果是什么?
1.類的靜態(tài)方法
package com.journaldev.util;
public class Test {
? ?????? public static String toString(){
? ?????????? System.out.println("Test toString called");
? ?????? ???? return "";
? ????? }
? ?????? public static void main(String args[]){
? ?????????? System.out.println(toString());
? ? ? ? }
}
答案:代碼編譯會(huì)失敗,因?yàn)镺bject類方法不能用static關(guān)鍵詞修飾。你會(huì)得到一個(gè)編譯錯(cuò)誤“This static method cannot hide the instancemethod from Object”。理由是靜態(tài)方法屬于類,所有類的基類是Object,我們不能像在類中一樣在實(shí)例里面有相同名稱的方法。
2.靜態(tài)方法調(diào)用
package com.journaldev.util;?
public class Test {
? ?????? public static String foo(){
? ?????????? System.out.println("Test foo called");
? ?????????? return "";
? ? ? ? }
? ?????? public static void main(String args[]){
? ?????????? Test obj = null;
? ?????????? System.out.println(obj.foo());
? ? ? ? }
}
答案:這是個(gè)異常的情形。當(dāng)我們調(diào)用對(duì)象的方法為空時(shí)會(huì)報(bào)NullPointerException空指針異常。編譯器會(huì)給出“The static method foo() from the type Test should be accessed in a static way”,但是當(dāng)執(zhí)行時(shí)會(huì)打印“Test foo called”。
理想的情況是當(dāng)對(duì)象靜態(tài)方法調(diào)用時(shí)Java API應(yīng)該給出錯(cuò)誤而不是警告,但我認(rèn)為這樣強(qiáng)制的太晚了。大多數(shù)異常是即使對(duì)象這里為空,但調(diào)用靜態(tài)方法是還是能運(yùn)行。我認(rèn)為這里可以運(yùn)行是因?yàn)镴ava運(yùn)行時(shí)計(jì)算出foo()是一個(gè)靜態(tài)方法,而且在類加載到內(nèi)存中調(diào)用,而且不會(huì)用這個(gè)對(duì)象,所以沒(méi)有空指針異常。