相信今年很多面試的朋友都遇到一個(gè)問(wèn)題锨天,在刷題的時(shí)候一直在刷比較高級(jí)項(xiàng)目框架內(nèi)容,卻忘記了那些不該忘的基礎(chǔ)內(nèi)容.
萬(wàn)萬(wàn)沒(méi)想到剃毒,最后卻栽倒了基礎(chǔ)上面绍绘,下面為大家準(zhǔn)備了一些基礎(chǔ)項(xiàng)目題,大家可以查漏補(bǔ)缺下.
1.面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別
面向過(guò)程
優(yōu)點(diǎn): 性能比面向?qū)ο蟾叱僭撸驗(yàn)轭愓{(diào)用時(shí)需要實(shí)例化陪拘,開銷比較大,比較消耗資源;比如單片機(jī)纤壁、嵌入式開發(fā)左刽、
Linux/Unix 等一般采用面向過(guò)程開發(fā),性能是最重要的因素酌媒。
缺點(diǎn): 沒(méi)有面向?qū)ο笠拙S護(hù)欠痴、易復(fù)用、易擴(kuò)展
面向?qū)ο?/strong>
優(yōu)點(diǎn): 易維護(hù)秒咨、易復(fù)用喇辽、易擴(kuò)展,由于面向?qū)ο笥蟹庋b雨席、繼承菩咨、多態(tài)性的特性,可以設(shè)計(jì)出低耦合的系統(tǒng)陡厘,使系
統(tǒng)更加靈活抽米、更加易于維護(hù)
缺點(diǎn): 性能比面向過(guò)程低
2. Java 語(yǔ)言有哪些特點(diǎn)
1. 簡(jiǎn)單易學(xué);
2. 面向?qū)ο螅ǚ庋b糙置,繼承云茸,多態(tài));
3. 平臺(tái)無(wú)關(guān)性( Java 虛擬機(jī)實(shí)現(xiàn)平臺(tái)無(wú)關(guān)性)谤饭;
4. 可靠性标捺;
5. 安全性;
6. 支持多線程( C++ 語(yǔ)言沒(méi)有內(nèi)置的多線程機(jī)制揉抵,因此必須調(diào)用操作系統(tǒng)的多線程功能來(lái)進(jìn)行多線程程序設(shè)計(jì)亡容,而
Java 語(yǔ)言卻提供了多線程支持);
7. 支持網(wǎng)絡(luò)編程并且很方便( Java 語(yǔ)言誕生本身就是為簡(jiǎn)化網(wǎng)絡(luò)編程設(shè)計(jì)的功舀,因此 Java 語(yǔ)言不僅支持網(wǎng)絡(luò)編程而且
很方便)萍倡;
8. 編譯與解釋并存;
3. 關(guān)于 JVM JDK 和 JRE 最詳細(xì)通俗的解答
JVM
Java 虛擬機(jī)(JVM)是運(yùn)行 Java 字節(jié)碼的虛擬機(jī)辟汰。JVM 有針對(duì)不同系統(tǒng)的特定實(shí)現(xiàn)(Windows列敲,Linux阱佛,
macOS).
目的:是使用相同的字節(jié)碼,它們都會(huì)給出相同的結(jié)果.
什么是字節(jié)碼?采用字節(jié)碼的好處是什么?
在 Java 中戴而,JVM 可以理解的代碼就叫做字節(jié)碼(即擴(kuò)展名為 .class 的文件)凑术,它不面向任何特定的處理器,只面向
虛擬機(jī)所意。
Java 語(yǔ)言通過(guò)字節(jié)碼的方式淮逊,在一定程度上解決了傳統(tǒng)解釋型語(yǔ)言執(zhí)行效率低的問(wèn)題,同時(shí)又保留了解釋型語(yǔ)言可移
植的特點(diǎn)扶踊。
所以 Java 程序運(yùn)行時(shí)比較高效泄鹏,而且,由于字節(jié)碼并不專對(duì)一種特定的機(jī)器秧耗,因此备籽,Java 程序無(wú)須重新編譯便可在
多種不同的計(jì)算機(jī)上運(yùn)行。
Java 程序從源代碼到運(yùn)行一般有下面 3 步:
我們需要格外注意的是 .class->機(jī)器碼 這一步分井。
在這一步 jvm 類加載器首先加載字節(jié)碼文件车猬,然后通過(guò)解釋器逐行解釋執(zhí)行,這種方式的執(zhí)行速度會(huì)相對(duì)比較慢尺锚。
而且珠闰,有些方法和代碼塊是經(jīng)常需要被調(diào)用的,也就是所謂的熱點(diǎn)代碼瘫辩,所以后面引進(jìn)了 JIT 編譯器伏嗜,JIT 屬于運(yùn)行時(shí)
編譯。
當(dāng) JIT 編譯器完成第一次編譯后杭朱,其會(huì)將字節(jié)碼對(duì)應(yīng)的機(jī)器碼保存下來(lái)阅仔,下次可以直接使用吹散。
而我們知道弧械,機(jī)器碼的運(yùn)行效率肯定是高于 Java 解釋器的。這也解釋了我們?yōu)槭裁唇?jīng)常會(huì)說(shuō) Java 是編譯與解釋共存
的語(yǔ)言空民。
HotSpot 采用了惰性評(píng)估(Lazy Evaluation)的做法刃唐,根據(jù)二八定律,消耗大部分系統(tǒng)資源的只有那一小部分的代碼(熱
點(diǎn)代碼)界轩,而這也就是 JIT 所需要編譯的部分画饥。
JVM 會(huì)根據(jù)代碼每次被執(zhí)行的情況收集信息并相應(yīng)地做出一些優(yōu)化,因此執(zhí)行的次數(shù)越多浊猾,它的速度就越快抖甘。
JDK 9 引入了一種新的編譯模式
AOT(Ahead of Time Compilation),它是直接將字節(jié)碼編譯成機(jī)器碼葫慎,這樣就避免了 JIT 預(yù)熱等各方面的開銷衔彻。JDK
支持分層編譯和 AOT 協(xié)作使用薇宠。
但是 ,AOT 編譯器的編譯質(zhì)量是肯定比不上 JIT 編譯器的艰额。
總結(jié):Java 虛擬機(jī)(JVM)是運(yùn)行 Java 字節(jié)碼的虛擬機(jī)澄港。JVM 有針對(duì)不同系統(tǒng)的特定實(shí)現(xiàn)(Windows,Linux柄沮,
macOS)回梧,目的是使用相同的字節(jié)碼,它們都會(huì)給出相同的結(jié)果祖搓。
字節(jié)碼和不同系統(tǒng)的 JVM 實(shí)現(xiàn)是 Java 語(yǔ)言“一次編譯狱意,隨處可以運(yùn)行”的關(guān)鍵所在。
JDK 和 JRE
JDK 是 Java Development Kit拯欧,它是功能齊全的 Java SDK髓涯。它擁有 JRE 所擁有的一切,還有編譯器(javac)和工具
(如 javadoc 和 jdb)哈扮。它能夠創(chuàng)建和編譯程序纬纪。
JRE 是 Java 運(yùn)行時(shí)環(huán)境。它是運(yùn)行已編譯 Java 程序所需的所有內(nèi)容的集合滑肉,包括 Java 虛擬機(jī)(JVM)包各,Java 類
庫(kù),java 命令和其他的一些基礎(chǔ)構(gòu)件靶庙。
但是问畅,它不能用于創(chuàng)建新程序。
如果你只是為了運(yùn)行一下 Java 程序的話六荒,那么你只需要安裝 JRE 就可以了护姆。
如果你需要進(jìn)行一些 Java 編程方面的工作,那么你就需要安裝 JDK 了掏击。
但是卵皂,這不是絕對(duì)的。有時(shí)砚亭,即使您不打算在計(jì)算機(jī)上進(jìn)行任何 Java 開發(fā)灯变,仍然需要安裝 JDK。
例如捅膘,如果要使用 JSP 部署 Web 應(yīng)用程序添祸,那么從技術(shù)上講,您只是在應(yīng)用程序服務(wù)器中運(yùn)行 Java 程序寻仗。那你為什么需要 JDK 呢刃泌?
因?yàn)閼?yīng)用程序服務(wù)器會(huì)將 JSP 轉(zhuǎn)換為 Java servlet,并且需要使用 JDK 來(lái)編譯servlet。
4. Oracle JDK 和 OpenJDK 的對(duì)比
可能在看這個(gè)問(wèn)題之前很多人和我一樣并沒(méi)有接觸和使用過(guò) OpenJDK 耙替。那么Oracle 和 OpenJDK 之間是否存在重大差異鲤遥?
下面通過(guò)我通過(guò)我收集到一些資料對(duì)你解答這個(gè)被很多人忽視的問(wèn)題。
對(duì)于 Java 7林艘,沒(méi)什么關(guān)鍵的地方盖奈。
OpenJDK 項(xiàng)目主要基于 Sun 捐贈(zèng)的 HotSpot源代碼。此外狐援,OpenJDK 被選為 Java 7 的參考實(shí)現(xiàn)钢坦,由 Oracle 工程師
維護(hù)。
關(guān)于 JVM啥酱,JDK爹凹,JRE 和 OpenJDK 之間的區(qū)別.
一個(gè)更詳細(xì)的答案:
問(wèn):OpenJDK 存儲(chǔ)庫(kù)中的源代碼與用于構(gòu)建 Oracle JDK 的代碼之間有什么區(qū)別?
答:非常接近 - 我們的 Oracle JDK 版本構(gòu)建過(guò)程基于 OpenJDK 7 構(gòu)建镶殷,只添加了幾個(gè)部分禾酱,例如部署代碼,其中包
括 Oracle 的 Java 插件和 Java WebStart的實(shí)現(xiàn)绘趋,以及一些封閉的源代碼派對(duì)組件颤陶,如圖形光柵化器,一些開源的第
三方組件陷遮,如 Rhino滓走,以及一些零碎的東西,如附加文檔或第三方字體帽馋。
展望未來(lái)搅方,我們的目的是開源 Oracle JDK 的所有部分,除了我們考慮商業(yè)功能的部分绽族。
總結(jié):
1. Oracle JDK 版本將每三年發(fā)布一次姨涡,而 OpenJDK 版本每三個(gè)月發(fā)布一次;
2. OpenJDK 是一個(gè)參考模型并且是完全開源的吧慢,而 Oracle JDK 是OpenJDK 的一個(gè)實(shí)現(xiàn)涛漂,并不是完全開源的;
3. Oracle JDK 比 OpenJDK 更穩(wěn)定娄蔼。OpenJDK 和 Oracle JDK 的代碼幾乎相同怖喻,但 Oracle JDK 有更多的類和一些錯(cuò)
誤修復(fù)。
因此岁诉,如果您想開發(fā)企業(yè)/商業(yè)軟件,我建議您選擇 Oracle JDK跋选,因?yàn)樗?jīng)過(guò)了徹底的測(cè)試和穩(wěn)定涕癣。
某些情況下,有些人提到在使用 OpenJDK 可能會(huì)遇到了許多應(yīng)用程序崩潰的問(wèn)題,但是坠韩,只需切換到 Oracle JDK 就
可以解決問(wèn)題距潘;
4. 頂級(jí)公司正在使用 Oracle JDK,例如 Android Studio只搁,Minecraft 和IntelliJ IDEA 開發(fā)工具音比,其中 Open JDK 不太
受歡迎;
5. 在響應(yīng)性和 JVM 性能方面氢惋,Oracle JDK 與 OpenJDK 相比提供了更好的性能洞翩;
6. Oracle JDK 不會(huì)為即將發(fā)布的版本提供長(zhǎng)期支持,用戶每次都必須通過(guò)更新到最新版本獲得支持來(lái)獲取最新版本焰望;
7. Oracle JDK 根據(jù)二進(jìn)制代碼許可協(xié)議獲得許可骚亿,而 OpenJDK 根據(jù) GPLv2 許可獲得許可。
5. Java 和 C++的區(qū)別
我知道很多人沒(méi)學(xué)過(guò) C++熊赖,但是面試官就是沒(méi)事喜歡拿咱們 Java 和 C++ 比呀来屠!沒(méi)辦法!U痧摹俱笛!就算沒(méi)學(xué)過(guò) C++,也要記下來(lái)传趾!
都是面向?qū)ο蟮恼Z(yǔ)言嫂粟,都支持封裝、繼承和多態(tài)
Java 不提供指針來(lái)直接訪問(wèn)內(nèi)存墨缘,程序內(nèi)存更加安全
Java 的類是單繼承的星虹,C++ 支持多重繼承;雖然 Java 的類不可以多繼承镊讼,但是接口可以多繼承宽涌。
Java 有自動(dòng)內(nèi)存管理機(jī)制,不需要程序員手動(dòng)釋放無(wú)用內(nèi)存
6. 什么是 Java 程序的主類 應(yīng)用程序和小程序的主類有何不同
一個(gè)程序中可以有多個(gè)類蝶棋,但只能有一個(gè)類是主類卸亮。
在 Java 應(yīng)用程序中,這個(gè)主類是指包含 main()方法的類玩裙。而在 Java 小程序中兼贸,這個(gè)主類是一個(gè)繼承自系統(tǒng)類
JApplet 或 Applet 的子類。
應(yīng)用程序的主類不一定要求是 public類吃溅,但小程序的主類要求必須是 public 類溶诞。主類是 Java 程序執(zhí)行的入口點(diǎn)。
7. Java 應(yīng)用程序與小程序之間有那些差別
簡(jiǎn)單說(shuō)應(yīng)用程序是從主線程啟動(dòng)(也就是 main() 方法)决侈。
applet 小程序沒(méi)有main 方法螺垢,主要是嵌在瀏覽器頁(yè)面上運(yùn)行(調(diào)用 init()線程或者 run()來(lái)啟動(dòng)),嵌入瀏覽器這點(diǎn)跟
flash 的小游戲類似。
8. 字符型常量和字符串常量的區(qū)別
1. 形式上: 字符常量是單引號(hào)引起的一個(gè)字符 字符串常量是雙引號(hào)引起的若干個(gè)字符
2. 含義上: 字符常量相當(dāng)于一個(gè)整形值( ASCII 值),可以參加表達(dá)式運(yùn)算 字符串常量代表一個(gè)地址值(該字符串在內(nèi)存中
存放位置)
3. 占內(nèi)存大小 字符常量只占 2 個(gè)字節(jié) 字符串常量占若干個(gè)字節(jié)(至少一個(gè)字符結(jié)束標(biāo)志) (注意: char 在 Java 中占兩
個(gè)字節(jié))
9. 構(gòu)造器 Constructor 是否可被 override
在講繼承的時(shí)候我們就知道父類的私有屬性和構(gòu)造方法并不能被繼承枉圃,所以Constructor 也就不能被 override(重寫),
但是可以 overload(重載),所以你可以看到一個(gè)類中有多個(gè)構(gòu)造函數(shù)的情況功茴。
10. 重載和重寫的區(qū)別
重載: 發(fā)生在同一個(gè)類中,方法名必須相同孽亲,參數(shù)類型不同坎穿、個(gè)數(shù)不同、順序不同返劲,方法返回值和訪問(wèn)修飾符可
以不同玲昧,發(fā)生在編譯時(shí)。
重寫: 發(fā)生在父子類中旭等,方法名酌呆、參數(shù)列表必須相同,返回值范圍小于等于父類搔耕,拋出的異常范圍小于等于父
類隙袁,訪問(wèn)修飾符范圍大于等于父類;
如果父類方法訪問(wèn)修飾符為 private 則子類就不能重寫該方法弃榨。
11. Java 面向?qū)ο缶幊倘筇匦? 封裝 繼承 多態(tài)
封裝
封裝把一個(gè)對(duì)象的屬性私有化菩收,同時(shí)提供一些可以被外界訪問(wèn)的屬性的方法,如果屬性不想被外界訪問(wèn)鲸睛,我們大可不
必提供方法給外界訪問(wèn)娜饵。但是如果一個(gè)類沒(méi)有提供給外界訪問(wèn)的方法,那么這個(gè)類也沒(méi)有什么意義了官辈。
繼承
繼承是使用已存在的類的定義作為基礎(chǔ)建立新類的技術(shù)箱舞,新類的定義可以增加新的數(shù)據(jù)或新的功能,也可以用父類的
功能拳亿,但不能選擇性地繼承父類晴股。通過(guò)使用繼承我們能夠非常方便地復(fù)用以前的代碼。
關(guān)于繼承如下 3 點(diǎn)請(qǐng)記追慰:
1. 子類擁有父類非 private 的屬性和方法电湘。
2. 子類可以擁有自己屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展鹅经。
3. 子類可以用自己的方式實(shí)現(xiàn)父類的方法寂呛。(以后介紹)。
多態(tài)
所謂多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定瘾晃,而是
在程序運(yùn)行期間才確定贷痪,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中
實(shí)現(xiàn)的方法酗捌,必須在由程序運(yùn)行期間才能決定呢诬。
在 Java 中有兩種形式可以實(shí)現(xiàn)多態(tài):繼承(多個(gè)子類對(duì)同一方法的重寫)和接口(實(shí)現(xiàn)接口并覆蓋接口中同一方法)涌哲。
12. String StringBuffer 和 StringBuilder 的區(qū)別
是什么 String 為什么是不可變的
可變性簡(jiǎn)單的來(lái)說(shuō):
String 類中使用 final 關(guān)鍵字字符數(shù)組保存字符串胖缤,privatefinal char value[].
所以 String 對(duì)象是不可變的尚镰。
而 StringBuilder 與StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中
也是使用字符數(shù)組保存字符串 char[]value 但是沒(méi)有用 final 關(guān)鍵字修飾哪廓,所以這兩種對(duì)象都是可變的狗唉。
StringBuilder 與 StringBuffer 的構(gòu)造方法都是調(diào)用父類構(gòu)造方法也就是AbstractStringBuilder 實(shí)現(xiàn)的.
大家可以自行查閱源碼:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
char\[\] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value \= new char\[capacity\];
}
線程安全性
String 中的對(duì)象是不可變的,也就可以理解為常量涡真,線程安全分俯。
AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字符串的基本操作.
如 expandCapacity哆料、append缸剪、insert、indexOf 等公共方法杏节。
StringBuffer 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線程安全的典阵。StringBuilder 并沒(méi)有對(duì)方法進(jìn)行加
同步鎖玄渗,所以是非線程安全的甜紫。
性能
每次對(duì) String 類型進(jìn)行改變的時(shí)候额嘿,都會(huì)生成一個(gè)新的 String 對(duì)象,然后將
指針指向新的 String 對(duì)象谣光。StringBuffer 每次都會(huì)對(duì) StringBuffer 對(duì)象本身進(jìn)行操作,而不是生成新的對(duì)象并改變對(duì)象引用越妈。
相同情況下使用StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升展氓,但卻要冒多線程不安全的
風(fēng)險(xiǎn)穆趴。
對(duì)于三者使用的總結(jié):
1. 操作少量的數(shù)據(jù) = String
2. 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) = StringBuilder
3. 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) = StringBuffer
13. 自動(dòng)裝箱與拆箱
裝箱:將基本類型用它們對(duì)應(yīng)的引用類型包裝起來(lái);
拆箱:將包裝類型轉(zhuǎn)換為基本數(shù)據(jù)類型带饱;
14. 在一個(gè)靜態(tài)方法內(nèi)調(diào)用一個(gè)非靜態(tài)成員為什么是非法的.
由于靜態(tài)方法可以不通過(guò)對(duì)象進(jìn)行調(diào)用毡代,因此在靜態(tài)方法里阅羹,不能調(diào)用其他非
靜態(tài)變量勺疼,也不可以訪問(wèn)非靜態(tài)變量成員。
15. 在 Java 中定義一個(gè)不做事且沒(méi)有參數(shù)的構(gòu)造
方法的作用
Java 程序在執(zhí)行子類的構(gòu)造方法之前捏鱼,如果沒(méi)有用 super() 來(lái)調(diào)用父類特定的構(gòu)造方法执庐,則會(huì)調(diào)用父類中“沒(méi)有參數(shù)的
構(gòu)造方法”。
因此导梆,如果父類中只定義了有參數(shù)的構(gòu)造方法轨淌,而在子類的構(gòu)造方法中又沒(méi)有用 super() 來(lái)調(diào)用父類中特定的構(gòu)造方
法,則編譯時(shí)將發(fā)生錯(cuò)誤看尼,因?yàn)?Java 程序在父類中找不到?jīng)]有參數(shù)的構(gòu)造方法可供執(zhí)行递鹉。解決辦法是在父類里加上一
個(gè)不做事且沒(méi)有參數(shù)的構(gòu)造方法。
16. import java 和 javax 有什么區(qū)別
剛開始的時(shí)候 JavaAPI 所必需的包是 java 開頭的包藏斩,javax 當(dāng)時(shí)只是擴(kuò)展API 包來(lái)說(shuō)使用躏结。
然而隨著時(shí)間的推移,javax 逐漸的擴(kuò)展成為 Java API 的組成部分狰域。
但是媳拴,將擴(kuò)展從 javax 包移動(dòng)到 java 包將是太麻煩了,最終會(huì)破壞一堆現(xiàn)有的代碼绍昂。因此麻昼,最終決定 javax 包將成為
標(biāo)準(zhǔn) API 的一部分亡呵。所以,實(shí)際上 java 和 javax 沒(méi)有區(qū)別子巾。這都是一個(gè)名字。
17. 接口和抽象類的區(qū)別是什么
1. 接口的方法默認(rèn)是 public小压,所有方法在接口中不能有實(shí)現(xiàn)(Java 8 開始接口方法可以有默認(rèn)實(shí)現(xiàn))线梗,抽象類可以有
非抽象的方法.
2. 接口中的實(shí)例變量默認(rèn)是 final 類型的,而抽象類中則不一定
3. 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口场航,但最多只能實(shí)現(xiàn)一個(gè)抽象類
4. 一個(gè)類實(shí)現(xiàn)接口的話要實(shí)現(xiàn)接口的所有方法缠导,而抽象類不一定
5. 接口不能用 new 實(shí)例化,但可以聲明溉痢,但是必須引用一個(gè)實(shí)現(xiàn)該接口的對(duì)象 從設(shè)計(jì)層面來(lái)說(shuō)僻造,抽象是對(duì)類的抽
象憋他,是一種模板設(shè)計(jì),接口是行為的抽象髓削,是一種行為的規(guī)范竹挡。
18. 成員變量與局部變量的區(qū)別有那些
1. 從語(yǔ)法形式上,看成員變量是屬于類的立膛,而局部變量是在方法中定義的變量或是方法的參數(shù)揪罕;成員變量可以被
public,private,static 等修飾符所修飾,而局部變量不能被訪問(wèn)控制修飾符及 static 所修飾宝泵;但是好啰,成員變量和局部變量
都能被 final 所修飾;
2. 從變量在內(nèi)存中的存儲(chǔ)方式來(lái)看儿奶,成員變量是對(duì)象的一部分框往,而對(duì)象存在于堆內(nèi)存,局部變量存在于棧內(nèi)存3. 從變
量在內(nèi)存中的生存時(shí)間上看闯捎,成員變量是對(duì)象的一部分椰弊,它隨著對(duì)象的創(chuàng)建而存在,而局部變量隨著方法的調(diào)用而自
動(dòng)消失瓤鼻。
3. 成員變量如果沒(méi)有被賦初值秉版,則會(huì)自動(dòng)以類型的默認(rèn)值而賦值(一種情況例外被 final 修飾的成員變量也必須顯示地
賦值);而局部變量則不會(huì)自動(dòng)賦值茬祷。
19. 創(chuàng)建一個(gè)對(duì)象用什么運(yùn)算符?對(duì)象實(shí)體與對(duì)象引用有何不同?
new 運(yùn)算符清焕,new 創(chuàng)建對(duì)象實(shí)例(對(duì)象實(shí)例在堆內(nèi)存中),對(duì)象引用指向?qū)ο髮?shí)例(對(duì)象引用存放在棧內(nèi)存中)牲迫。一
個(gè)對(duì)象引用可以指向 0 個(gè)或 1 個(gè)對(duì)象(一根繩子可以不系氣球耐朴,也可以系一個(gè)氣球);一個(gè)對(duì)象可以有 n 個(gè)引用指向
它(可以用 n 條繩子系住一個(gè)氣球)。
20. 什么是方法的返回值?返回值在類的方法里的作用是什么?
方法的返回值是指我們獲取到的某個(gè)方法體中的代碼執(zhí)行后產(chǎn)生的結(jié)果m镌鳌(前提是該方法可能產(chǎn)生結(jié)果)筛峭。
返回值作用:接收出結(jié)果,使得它可以用于其他的操作.
21. 一個(gè)類的構(gòu)造方法的作用是什么 若一個(gè)類沒(méi)有聲明構(gòu)造方法,該程序能正確執(zhí)行嗎 ?為什么?
主要作用是完成對(duì)類對(duì)象的初始化工作陪每∮跋可以執(zhí)行。
因?yàn)橐粋€(gè)類即使沒(méi)有聲明構(gòu)造方法也會(huì)有默認(rèn)的不帶參數(shù)的構(gòu)造方法檩禾。
22. 構(gòu)造方法有哪些特性
1. 名字與類名相同挂签;
2. 沒(méi)有返回值,但不能用 void 聲明構(gòu)造函數(shù)盼产;
3. 生成類的對(duì)象時(shí)自動(dòng)執(zhí)行饵婆,無(wú)需調(diào)用。
23. 靜態(tài)方法和實(shí)例方法有何不同
1. 在外部調(diào)用靜態(tài)方法時(shí)戏售,可以使用"類名.方法名"的方式侨核,也可以使用"對(duì)象名.方法名"的方式草穆。而實(shí)例方法只有后面
這種方式。也就是說(shuō)搓译,調(diào)用靜態(tài)方法可以無(wú)需創(chuàng)建對(duì)象悲柱。
2. 靜態(tài)方法在訪問(wèn)本類的成員時(shí),只允許訪問(wèn)靜態(tài)成員(即靜態(tài)成員變量
和靜態(tài)方法)些己,而不允許訪問(wèn)實(shí)例成員變量和實(shí)例方法豌鸡;實(shí)例方法則無(wú)此限制.
24. 對(duì)象的相等與指向他們的引用相等,兩者有什么不同段标?
對(duì)象的相等涯冠,比的是內(nèi)存中存放的內(nèi)容是否相等。而引用相等怀樟,比較的是他們
指向的內(nèi)存地址是否相等功偿。
25. 在調(diào)用子類構(gòu)造方法之前會(huì)先調(diào)用父類沒(méi)有參數(shù)的構(gòu)造方法,其目的是?
幫助子類做初始化工作往堡。
26. == 與 equals(重要)
== : 它的作用是判斷兩個(gè)對(duì)象的地址是不是相等。即共耍,判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象虑灰。(基本數(shù)據(jù)類型==比較的是
值,引用數(shù)據(jù)類型==比較的是內(nèi)存地址)
**equals() : **它的作用也是判斷兩個(gè)對(duì)象是否相等痹兜。
但它一般有兩種使用情況:
情況 1:類沒(méi)有覆蓋 equals() 方法穆咐。則通過(guò) equals() 比較該類的兩個(gè)對(duì)象時(shí),等價(jià)于通過(guò)“==”比較這兩個(gè)對(duì)象字旭。
情況 2:類覆蓋了 equals() 方法对湃。一般,我們都覆蓋 equals() 方法來(lái)兩個(gè)對(duì)象的內(nèi)容相等遗淳;若它們的內(nèi)容相等拍柒,則
回 true (即,認(rèn)為這兩個(gè)對(duì)象相等)屈暗。
舉個(gè)例子:
public static void main(String\[\] args) {
String a \= new String("ab"); // a 為一個(gè)引用
String b \= new String("ab"); // b 為另一個(gè)引用,對(duì)象的內(nèi)容一樣
String aa \= "ab"; // 放在常量池中
String bb \= "ab"; // 從常量池中查找
if (aa \== bb) // true
System.out.println("aa==bb");
if (a \== b) // false拆讯,非同一對(duì)象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 \== 42.0) { // true
System.out.println("true");
}
}
}
說(shuō)明:
String 中的 equals 方法是被重寫過(guò)的,因?yàn)?object 的 equals 方法是比較的對(duì)象的內(nèi)存地址养叛,而 String 的 equals 方法比較的是對(duì)象的值种呐。
當(dāng)創(chuàng)建 String 類型的對(duì)象時(shí),虛擬機(jī)會(huì)在常量池中查找有沒(méi)有已經(jīng)存在的值和要?jiǎng)?chuàng)建的值相同的對(duì)象弃甥,如果有就把它賦給當(dāng)前引用爽室。如果沒(méi)有就在常量池中重新創(chuàng)建一個(gè) String 對(duì)象。
27. hashCode 與 equals(重要)面試官可能會(huì)問(wèn)你:“你重寫過(guò) hashcode 和 equals 么淆攻,為什么重寫 equals
時(shí)必須重寫 hashCode 方法阔墩?
hashCode()介紹
hashCode() 的作用是獲取哈希碼掉缺,也稱為散列碼;它實(shí)際上是返回一個(gè) int 整數(shù)戈擒。
這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置眶明。hashCode() 定義在 JDK 的 Object.java 中,這就意味著
Java 中的任何類都包含有 hashCode() 函數(shù)筐高。
散列表存儲(chǔ)的是鍵值對(duì)(key-value)搜囱,它的特點(diǎn)是:能根據(jù)“鍵”快速的檢索出對(duì)應(yīng)的“值”。這其中就利用到了散列碼柑土!
(可以快速找到所需要的對(duì)象)
為什么要有 hashCode
我們以“HashSet 如何檢查重復(fù)”為例子來(lái)說(shuō)明為什么要有 hashCode:
當(dāng)你把對(duì)象加入 HashSet 時(shí)蜀肘,HashSet 會(huì)先計(jì)算對(duì)象的 hashcode 值來(lái)判斷對(duì)象加入的位置,同時(shí)也會(huì)與其他已經(jīng)加
入的對(duì)象的 hashcode 值作比較稽屏,如果沒(méi)有相符的 hashcode扮宠,HashSet 會(huì)假設(shè)對(duì)象沒(méi)有重復(fù)出現(xiàn)。
但是如果發(fā)現(xiàn)有相同 hashcode 值的對(duì)象狐榔,這時(shí)會(huì)調(diào)用 equals()方法來(lái)檢查 hashcode 相等的對(duì)象是否真的相同坛增。
如果兩者相同,HashSet 就不會(huì)讓其加入操作成功薄腻。
如果不同的話收捣,就會(huì)重新散列到其他位置。
這樣我們就大大減少了 equals 的次數(shù)庵楷,相應(yīng)就大大提高了執(zhí)行速度罢艾。
hashCode()與 equals()的相關(guān)規(guī)定.
1. 如果兩個(gè)對(duì)象相等,則 hashcode 一定也是相同的
2. 兩個(gè)對(duì)象相等,對(duì)兩個(gè)對(duì)象分別調(diào)用 equals 方法都返回 true
3. 兩個(gè)對(duì)象有相同的 hashcode 值尽纽,它們也不一定是相等的
4. 因此咐蚯,equals 方法被覆蓋過(guò),則 hashCode 方法也必須被覆蓋
5. hashCode() 的默認(rèn)行為是對(duì)堆上的對(duì)象產(chǎn)生獨(dú)特值弄贿。如果沒(méi)有重寫hashCode()春锋,則該 class 的兩個(gè)對(duì)象無(wú)論如何
都不會(huì)相等(即使這兩個(gè)對(duì)象指向相同的數(shù)據(jù))
28. 為什么 Java 中只有值傳遞
為什么 Java 中只有值傳遞?
29. 簡(jiǎn)述線程挎春,程序看疙、進(jìn)程的基本概念。以及他們之間關(guān)系是什么直奋?
線程與進(jìn)程相似能庆,但線程是一個(gè)比進(jìn)程更小的執(zhí)行單位。一個(gè)進(jìn)程在其執(zhí)行的過(guò)程中可以產(chǎn)生多個(gè)線程脚线。
與進(jìn)程不同的是同類的多個(gè)線程共享同一塊內(nèi)存空間和一組系統(tǒng)資源搁胆,所以系統(tǒng)在產(chǎn)生一個(gè)線程,或是在各個(gè)線程之
間作切換工作時(shí),負(fù)擔(dān)要比進(jìn)程小得多渠旁,也正因?yàn)槿绱伺世€程也被稱為輕量級(jí)進(jìn)程。
程序是含有指令和數(shù)據(jù)的文件顾腊,被存儲(chǔ)在磁盤或其他的數(shù)據(jù)存儲(chǔ)設(shè)備中粤铭,也就是說(shuō)程序是靜態(tài)的代碼。
進(jìn)程是程序的一次執(zhí)行過(guò)程杂靶,是系統(tǒng)運(yùn)行程序的基本單位梆惯,因此進(jìn)程是動(dòng)態(tài)的。
系統(tǒng)運(yùn)行一個(gè)程序即是一個(gè)進(jìn)程從創(chuàng)建吗垮,運(yùn)行到消亡的過(guò)程垛吗。簡(jiǎn)單來(lái)說(shuō),一個(gè)進(jìn)程就是一個(gè)執(zhí)行中的程序烁登,它在計(jì)算
機(jī)中一個(gè)指令接著一個(gè)指令地執(zhí)行著怯屉,同時(shí),每個(gè)進(jìn)程還占有某些系統(tǒng)資源如 CPU 時(shí)間饵沧,內(nèi)存空間锨络,文件,文件捷泞,輸
入輸出設(shè)備的使用權(quán)等等足删。換句話說(shuō),當(dāng)程序在執(zhí)行時(shí)锁右,將會(huì)被操作系統(tǒng)載入內(nèi)存中。
線程是進(jìn)程劃分成的更小的運(yùn)行單位讶泰。線程和進(jìn)程最大的不同在于基本上各進(jìn)程是獨(dú)立的咏瑟,而各線程則不一定,因?yàn)?/p>
同一進(jìn)程中的線程極有可能會(huì)相互影響痪署。
從另一角度來(lái)說(shuō)码泞,進(jìn)程屬于操作系統(tǒng)的范疇,主要是同一段時(shí)間內(nèi)狼犯,可以同時(shí)執(zhí)行一個(gè)以上的程序余寥,而線程則是在同
一程序內(nèi)幾乎同時(shí)執(zhí)行一個(gè)以上的程序段。
30. 線程有哪些基本狀態(tài)?
Java 線程在運(yùn)行的生命周期中的指定時(shí)刻只可能處于下面 6 種不同狀態(tài)的其中一個(gè)狀態(tài)悯森。
線程在生命周期中并不是固定處于某一個(gè)狀態(tài)而是隨著代碼的執(zhí)行在不同狀態(tài)之間切換宋舷。
Java 線程狀態(tài)變遷如下圖所示:
31 關(guān)于 final 關(guān)鍵字的一些總結(jié).
final 關(guān)鍵字主要用在三個(gè)地方:變量、方法瓢姻、類祝蝠。
1. 對(duì)于一個(gè) final 變量,如果是基本數(shù)據(jù)類型的變量,則其數(shù)值一旦在初始化之后便不能更改绎狭;如果是引用類型的變
量细溅,則在對(duì)其初始化之后便不能再讓其指向另一個(gè)對(duì)象。
2. 當(dāng)用 final 修飾一個(gè)類時(shí)儡嘶,表明這個(gè)類不能被繼承喇聊。final 類中的所有成員方法都會(huì)被隱式地指定為 final 方法。
3. 使用 final 方法的原因有兩個(gè)蹦狂。
第一個(gè)原因是把方法鎖定誓篱,以防任何繼承類修改它的含義;
第二個(gè)原因是效率鸥咖。在早期的 Java 實(shí)現(xiàn)版本中燕鸽,會(huì)將final 方法轉(zhuǎn)為內(nèi)嵌調(diào)用。
但是如果方法過(guò)于龐大啼辣,可能看不到內(nèi)嵌調(diào)用帶來(lái)的任何性能提升(現(xiàn)在的 Java 版本已經(jīng)不需要使用 final 方法進(jìn)行
這些優(yōu)化了)啊研。類中所有的 private 方法都隱式地指定為 final。
32 Java 中的異常處理Java 異常類層次結(jié)構(gòu)圖
在 Java 中鸥拧,所有的異常都有一個(gè)共同的祖先 java.lang 包中的 Throwable類党远。
Throwable有兩個(gè)重要的子類:Exception(異常) 和 Error(錯(cuò)誤) .
二者都是 Java 異常處理的重要子類,各自都包含大量子類.
Error(錯(cuò)誤):是程序無(wú)法處理的錯(cuò)誤富弦,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問(wèn)題沟娱。
大多數(shù)錯(cuò)誤與代碼編寫者執(zhí)行的操作無(wú)關(guān),而表示代碼運(yùn)行時(shí) JVM(Java 虛擬機(jī))出現(xiàn)的問(wèn)題腕柜。例如济似,Java 虛擬機(jī)
運(yùn)行錯(cuò)誤(Virtual MachineError),當(dāng)JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí)盏缤,將出現(xiàn) OutOfMemoryError砰蠢。
這些異常發(fā)生時(shí),Java 虛擬機(jī)(JVM)一般會(huì)選擇線程終止唉铜。
這些錯(cuò)誤表示故障發(fā)生于虛擬機(jī)自身台舱、或者發(fā)生在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如Java 虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual
MachineError)潭流、類定義錯(cuò)誤(NoClassDefFoundError)等竞惋。
這些錯(cuò)誤是不可查的,因?yàn)樗鼈冊(cè)趹?yīng)用程序的控制和處理能力之 外灰嫉,而且絕大多數(shù)是程序運(yùn)行時(shí)不允許出現(xiàn)的狀況拆宛。
對(duì)于設(shè)計(jì)合理的應(yīng)用程序來(lái)說(shuō),即使確實(shí)發(fā)生了錯(cuò)誤熬甫,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況胰挑。
在 Java 中蔓罚,錯(cuò)誤通過(guò) Error 的子類描述。
Exception(異常):是程序本身可以處理的異常瞻颂。Exception 類有一個(gè)重要的子類 RuntimeException豺谈。
RuntimeException 異常由 Java 虛擬機(jī)拋出。
NullPointerException(要訪問(wèn)的變量沒(méi)有引用任何對(duì)象時(shí)贡这,拋出該異常)茬末、ArithmeticException(算術(shù)運(yùn)算異常,一
個(gè)整數(shù)除以 0 時(shí)盖矫,拋出該異常)和ArrayIndexOutOfBoundsException (下標(biāo)越界異常).
注意異常和錯(cuò)誤的區(qū)別:
異常能被程序本身可以處理丽惭,錯(cuò)誤是無(wú)法處理。
Throwable 類常用方法:
public string getMessage():返回異常發(fā)生時(shí)的詳細(xì)信息
public string toString():返回異常發(fā)生時(shí)的簡(jiǎn)要描述
public string getLocalizedMessage():返回異常對(duì)象的本地化信息辈双。
使用 Throwable 的子類覆蓋這個(gè)方法责掏,可以聲稱本地化信息。
如果子類沒(méi)有覆蓋該方法湃望,則該方法返回的信息與 getMessage()返回的結(jié)果相同
public void printStackTrace():在控制臺(tái)上打印 Throwable 對(duì)象封裝的
異常信息
異常處理總結(jié)
** try 塊:**用于捕獲異常换衬。其后可接零個(gè)或多個(gè) catch 塊,如果沒(méi)有 catch塊证芭,則必須跟一個(gè) finally 塊瞳浦。
catch 塊:用于處理 try 捕獲到的異常。? finally 塊:無(wú)論是否捕獲或處理異常废士,finally 塊里的語(yǔ)句都會(huì)被執(zhí)行叫潦。
當(dāng)在 try 塊或 catch 塊中遇到 return 語(yǔ)句時(shí),finally 語(yǔ)句塊將在方法返回之前被執(zhí)行官硝。
在以下 4 種特殊情況下矗蕊,finally 塊不會(huì)被執(zhí)行:
1. 在 finally 語(yǔ)句塊中發(fā)生了異常。
2. 在前面的代碼中用了 System.exit()退出程序氢架。
3. 程序所在的線程死亡拔妥。
4. 關(guān)閉 CPU。
33 Java 序列化中如果有些字段不想進(jìn)行序列化 怎么辦达箍?
對(duì)于不想進(jìn)行序列化的變量,使用 transient 關(guān)鍵字修飾铺厨。
transient 關(guān)鍵字的作用是:阻止實(shí)例中那些用此關(guān)鍵字修飾的的變量序列化缎玫;
當(dāng)對(duì)象被反序列化時(shí),被 transient 修飾的變量值不會(huì)被持久化和恢復(fù)解滓。
transient 只能修飾變量赃磨,不能修飾類和方法。
34 獲取用鍵盤輸入常用的的兩種方法.
方法 1:通過(guò) Scanner
Scanner input \= new Scanner(System.in);
String s \= input.nextLine();
input.close()````````
方法 2:通過(guò) BufferedReader
BufferedReader input \= new BufferedReader(new InputStreamReader(System.in));
String s \= input.readLine();
**上面的這些面試題都整理成了PDF文檔洼裤,希望能幫助到你面試前的復(fù)習(xí)并找到一個(gè)好的工作邻辉,相對(duì)來(lái)說(shuō)也節(jié)省了你在網(wǎng)上搜索資料的時(shí)間來(lái)學(xué)習(xí)!!值骇!**
**附歡迎關(guān)注我的公種號(hào):it資源之家 莹菱,掃描下面二維碼即可領(lǐng)取更多一線大廠Java面試題資料!**
![](https://upload-images.jianshu.io/upload_images/20326660-5e1079ddc9d5531f.png)
## 最后
**歡迎大家評(píng)論區(qū)一起交流吱瘩,相互提升道伟;整理資料不易,如果喜歡文章記得點(diǎn)個(gè)贊哈使碾,感謝大家支持C刍铡!票摇!**