java面试题-基础篇(万字总结,带答案,面试官问烂,跳槽必备)
👀個人主頁: Java李小立
后面會持續更新java面試專欄,請持續關注
如果文章對你有幫助、歡迎關注、點贊、收藏(一鍵三連??????)
面試寶典列表(持續更新):
| 1 | Java基礎篇 | (點擊跳轉)java面試寶典-基礎篇 |
| 2 | Java集合框架篇 | (點擊跳轉)java面試寶典-集合框架篇 |
| 3 | Java多線程篇 | (點擊跳轉)java面試寶典- 多線程篇 |
| 4 | JVM篇 | 待分享 |
| 5 | Spring篇 | 待分享 |
| 6 | Mybatis篇 | 待分享 |
| 7 | SpringcCloud篇 | 待分享 |
| 8 | Redis篇 | 待分享 |
| 9 | Mysql篇 | 待分享 |
| 10 | dubbo篇 | 待分享 |
| 11 | zookeeper篇 | 待分享 |
| 12 | kafka篇 | 待分享 |
| 13 | RocketMq篇 | 待分享 |
| 14 | Nacos篇 | 待分享 |
(一)Java基礎
1.1.Java歷史簡述
- 1991 年Sun公司的James Gosling(詹姆斯?高斯林)等人開始開發名稱為 Oak
的語言,希望專攻計算機在家電產品上的嵌入式應用(如電視機頂盒、面包烤箱、移動電話等)。 - 1995年將Oak語言更名為Java;
- 2009年,甲骨文公司宣布收購Sun公司。
1.2. Java語言的特點
1.3. 面向對象與面向過程對比。
我們都知道Java的核心思想是面向對象,Java中萬事萬物皆對象,那么面向對象與面向過程有什么不同呢?
(1).面向過程
優點: 性能比面向對象高,因為類調用時需要實例化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、Linux/Unix等一般采用面向過程開發,性能是最重要的因素。
缺點: 沒有面向對象易維護、易復用、易擴展。
(2).面向對象
優點: 易維護、易復用、易擴展,由于面向對象有封裝、繼承、多態性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易于維護。
缺點: 性能比面向過程低。
1.4. Java平臺的三個版本J2EE、J2SE、J2ME。
JavaSE:即Java標準版,主要用于開發和部署桌面、例如,Java應用程序開發平臺Eclipse(常說的C\S架構)。
JavaEE:即Java企業版,主要針對企業應用的開發。例如,電商網站(常說的B\S架構)。
JavaME:即Java微型版,主要針對移動設備和嵌入式設備。例如,手機、PDA、電視機頂盒等等。
注:從JDK 5.0開始 J2EE 改名為 java EE,J2SE 改名為 java SE,J2ME 改名成 java ME。
1.5. JDK、JRE、JVM之間的區別于關系。
LZ身邊很多Java程序員,雖然寫了很久的代碼,但問他們jre 和 jdk 之間有什么關系,jvm 又是什么東西,很多人都講的不是特別清楚,作為一個合格的Java程序員了解這方面的基礎理論知識是很必要的。
(1).三者之間的區別:
JDK:(Java Development Kit)即java的開發與運行環境,他除了包含完整的JRE之外,還包含了供開發者使用的工具包。
JRE:(Java Runtime Environment)即Java運行環境,非開發者只需要安裝 JRE來運行程序, 它包含java運行的所需的類庫+JVM(java虛擬機)。
JVM: (Java Virtual Machine) 即Java虛擬機, 當我們運行一個程序時,JVM 負責將字節碼轉換為特定機器代碼,JVM 提供了內存管理/垃圾回收和安全機制等。這種獨立于硬件和操作系統,正是 java 程序可以一次編寫多處執行的原因。
(2).三者之間的關系
1.6. 什么是Java環境變量?
讓java bin目錄下的工具,可以在任意目錄下運行,原理是將該工具所在目錄告訴了系統,當使用該工具時,由系統幫我們去找指定的目錄。
設置Path環境變量之后就可以在任何目錄下執行javac/java等工具命令了。 系統默認先去當前路徑下找要執行的程序,如果沒有,再去path中設置的路徑下找。
如果指定了classpath,那么會在指定的目錄下查找要運行的類文件(JDK1.5后不需要配置)
1.7. javac命令和java命令做什么事情呢?
java運行分兩部分:一個是編譯,一個是運行。
javac:負責的是編譯的部分,當執行javac時,會啟動java的編譯器程序。對指定擴展名的.java文件進行編譯。編譯后生成class文件。
java:負責運行的部分.會啟動jvm虛擬機,加載運行時所需的類庫,并對class文件進行執行.
1.8. 什么是字節碼,采用字節碼的好處是什么。
首先我們來談談Java文件類型,一共有兩種:
擴展名為Java,Java的源文件,編譯之前的純文本文件,用來儲存Java源代碼。
擴展名為class,Java 的類文件,編譯之后的二進制文件,存儲的是字節碼。
也就是說編譯后的.class文件存儲就是字節碼*。
采用字節碼的最大好處: 可以實現一次編譯到處運行,也就是java的與平臺無關性,它依靠不同平臺的Java虛擬機將編譯后的字節碼解釋成具體平臺上的機器指令執行。
1.9. import java和javax有什么區別
剛開始的時候 JavaAPI 所必需的包是 java 開頭的包,javax 當時只是擴展 API 包來說使用。然而隨著時間的推移,javax 逐漸的擴展成為 Java API 的組成部分。但是,將擴展從 javax 包移動到 java 包將是太麻煩了,最終會破壞一堆現有的代碼。因此,最終決定 javax 包將成為標準API的一部分。
所以,實際上java和javax沒有區別。這都是一個名字。
1.10. Java和C++的區別
都是面向對象的語言,都支持封裝、繼承和多態
Java 不提供指針來直接訪問內存,程序內存更加安全
Java 的類是單繼承的,C++ 支持多重繼承;雖然 Java 的類不可以多繼承,但是接口可以多繼承。
Java 有自動內存管理機制,不需要程序員手動釋放無用內存
1.11.Java數據類型
類、接口類型、數組類型、枚舉類型、注解類型。
基本數據類型 在被創建時,在棧上給其劃分一塊內存,將數值直接存儲在棧上。
引用數據類型 在被創建時,首先要在棧上給其引用(句柄)分配一塊內存,而對象的具體信息都存儲在堆內存上,然后由棧上面的引用指向堆中對象的地址。
1.12.Java訪問修飾符
1.13.標識符的命名規則。
標識符的含義: 是指在程序中,我們自己定義的內容,譬如,類的名字,方法名稱以及變量名稱等
等,都是標識符。
命名規則:(硬性要求) 標識符可以包含英文字母,0-9的數字,$以及_ 標識符不能以數字開頭 標
識符不是關鍵字
命名規范:(非硬性要求) 類名規范:首字符大寫,后面每個單詞首字母大寫(大駝峰式)。 變量
名規范:首字母小寫,后面每個單詞首字母大寫(小駝峰式)。 方法名規范:同變量名。
1.14.instanceof 關鍵字的作用
instanceof 嚴格來說是Java中的一個雙目運算符,用來測試一個對象是否為一個類的實例,用法
為:
其中 obj 為一個對象,Class 表示一個類或者一個接口,當 obj 為 Class 的對象,或者是其直接或間接子類,或者是其接口的實現類,結果result 都返回 true,否則返回false
1.15.Java自動裝箱與拆箱
裝箱就是自動將基本數據類型轉換為包裝器類型(int–>Integer);調用方法:Integer的
valueOf(int) 方法
拆箱就是自動將包裝器類型轉換為基本數據類型(Integer–>int)。調用方法:Integer的
intValue方法
在Java SE5之前,需要手動裝箱與拆箱Integer
//手動裝箱 Integer integer = Integer.valueOf(10); //手動拆箱 int i = num.intValue();而在從Java SE5開始就提供了自動裝箱的特性,如果要生成一個數值為10的Integer對象,只需要
這樣就可以了:
1.16. 字符型常量和字符串常量的區別
char與String
1.17.泛型常用特點 (待補充)
泛型是Java SE 1.5之后的特性
“泛型” 意味著編寫的代碼可以被不同類型的對象所重用。
使用泛型的好處?
以集合來舉例,使用泛型的好處是我們不必因為添加元素類型的不同而定義不同類型的集合,如整
型集合類,浮點型集合類,字符串集合類,我們可以定義一個集合來存放整型、浮點型,字符串型
數據,而這并不是最重要的,因為我們只要把底層存儲設置了Object即可,添加的數據全部都可向
上轉型為Object。 更重要的是我們可以通過規則按照自己的想法控制存儲的數據類型。
1.18. Java 面向對象編程三大特性:封裝、繼承、多態
封裝
封裝把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性的方法,如果屬性不想被外界訪問,我們大可不必提供方法給外界訪問。
繼承
繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過使用繼承我們能夠非常方便地復用以前的代碼 同時繼承也為實現多態做了鋪墊。
關于繼承
多態
所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時并不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。
1.19. 代碼中如何實現多態?
實現多態主要有以下三種方式:
1.20. 多態有什么好處?
允許不同類對象對同一消息做出響應,即同一消息可以根據發送對象的不同而采用多種不同的行為方式(發送消息就是函數調用)。主要有以下優點:
可替換性:多態對已存在代碼具有可替換性
可擴充性:增加新的子類不影響已經存在的類結構
接口性:多態是超類通過方法簽名,向子類提供一個公共接口,由子類來完善或者重寫它來實現的。
1.21. 接口和抽象類的區別是什么
| 默認方法 | 抽象類可以有默認的方法實現 | java 8之前,接口中不存在方法的實現. |
| 實現方式 | 子類使用extends關鍵字來繼承抽象類.如果子類不是抽象類,子類需要提供抽象類中所聲明方法的實現. | 子類使用implements來實現接口,需要提供接口中所有聲明的實現. |
| 構造器 | 抽象類中可以有構造器, | 接口中不能 |
| 和正常類區別 | 抽象類不能被實例化 | 接口則是完全不同的類型 |
| 訪問修飾符 | 抽象方法可以有public,protected和default等修飾 | 接口默認是public,不能使用其他修飾符 |
| 多繼承 | 一個子類只能存在一個父類 | 一個子類可以存在多個接口 |
| 添加新方法 | 想抽象類中添加新方法,可以提供默認的實現,因此可以不修改子類現有的代碼 | 如果往接口中添加新方法,則子類中需要實現該方法. |
1.22.接口的意義抽象類的意義?
接口的意義
接口的意義用三個詞就可以概括:規范,擴展,回調。
抽象類的意義
抽象類的意義可以用三句話來概括:
為其他子類提供一個公共的類型
封裝子類中重復定義的內容
定義抽象方法,子類雖然有不同的實現,但是定義時一致的
1.23. 重載和重寫的區別
重載: 發生在同一個類中,方法名必須相同,參數類型不同、個數不同、順序不同,方法返回值和訪問修飾符可以不同,發生在編譯時。
重寫: 發生在父子類中,方法名、參數列表必須相同,返回值范圍小于等于父類,拋出的異常范圍小于等于父類,訪問修飾符范圍大于等于父類;如果父類方法訪問修飾符為 private 則子類就不能重寫該方法。
1.24. 一個類的構造方法的作用是什么 若一個類沒有聲明構造方法,該程序能正確執行嗎 為什么
主要作用是完成對類對象的初始化工作??梢詧绦?。因為一個類即使沒有聲明構造方法也會有默認的不帶參數的構造方法。
1.25. 構造方法有哪些特性
1.26. 構造器 Constructor 是否可被 override
在講繼承的時候我們就知道父類的私有屬性和構造方法并不能被繼承,所以 Constructor 也就不能被 override(重寫),但是可以 overload(重載),所以你可以看到一個類中有多個構造函數的情況。
1.27. 在調用子類構造方法之前會先調用父類沒有參數的構造方法,其目的是?
幫助子類做初始化工作。
1.28. 在 Java 中定義一個不做事且沒有參數的構造方法的作用
Java 程序在執行子類的構造方法之前,如果沒有用 super() 來調用父類特定的構造方法,則會調用父類中“沒有參數的構造方法”。因此,如果父類中只定義了有參數的構造方法,而在子類的構造方法中又沒有用 super() 來調用父類中特定的構造方法,則編譯時將發生錯誤,因為 Java 程序在父類中找不到沒有參數的構造方法可供執行。解決辦法是在父類里加上一個不做事且沒有參數的構造方法。
1.29. 在一個靜態方法內調用一個非靜態成員為什么是非法的,靜態方法和實例方法有何不同?
為什么非法
由于靜態方法可以不通過對象進行調用,類的靜態成員(變量和方法)屬于類本身,在類加載的時候就會分配內存,可以通過類名直接去訪問;非靜態成員(變量和方法)屬于類的對象,所以只有在類的對象產生(創建類的實例)時才會分配內存,然后通過類的對象(實例)去訪問。
有何不同
在一個類的靜態成員中去訪問其非靜態成員之所以會出錯是
因為在類的非靜態成員不存在的時候類的靜態成員就已經存在了,訪問一個內存中不存在的東西當然會出錯:
1.30. 成員變量與局部變量的區別有那些
1.31. 什么是不可變對象?
不可變對象指對象一旦被創建,狀態就不能再改變。任何修改都會創建一個新的對象,如 String、Integer及其它包裝類。
1.32. java 創建對象的幾種方式
采用new(對象實例在堆內存中),對象引用指向對象實例(對象引用存放在棧內存中)
通過反射
采用clone
通過序列化機制
前2者都需要顯式地調用構造方法。造成耦合性最高的恰好是第一種,因此你發現無論什么框架,只要涉及到解耦必先減少new的使用。
1.33. Object中有哪些公共方法?
equals()
clone()
getClass()
notify(),notifyAll(),wait()
toString
finalize()
1.34. java當中的四種引用
強引用,軟引用,弱引用,虛引用。不同的引用類型主要體現在GC上:
而這樣 obj對象對后面new Object的一個強引用,只有當obj這個引用被釋放之后,對象才會被釋放**
可用場景: 創建緩存的時候,創建的對象放進緩存中,當內存不足時,JVM就會回收早先創建
的對象。
可用場景: Java源碼中的 java.util.WeakHashMap 中的 key 就是使用弱引用,我的理解就是,
一旦我不需要某個引用,JVM會自動幫我處理它,這樣我就不需要做其它操作
被用于引用銷毀前的處理工作。還有就是,虛引用創建的時候,必須帶有 ReferenceQueue ,
使用例子:
可用場景: 對象銷毀前的一些操作,比如說資源釋放等。
1.35. WeakReference與SoftReference的區別?
這點在四種引用類型中已經做了解釋,這里簡單說明一下即可:
雖然 WeakReference 與 SoftReference 都有利于提高 GC 和 內存的效率,但是 WeakReference ,一旦失去最后一個強引用,就會被 GC 回收,而軟引用雖然不能阻止被回收,但是可以延遲到 JVM 內存不足的時候。
1.36. 為什么要有不同的引用類型
不像C語言,我們可以控制內存的申請和釋放,在Java中有時候我們需要適當的控制對象被回收的時機,因此就誕生了不同的引用類型,可以說不同的引用類型實則是對GC回收時機不可控的妥協。有以下幾個使用場景可以充分的說明:
利用軟引用和弱引用解決OOM問題:用一個HashMap來保存圖片的路徑和相應圖片對象關聯的軟引用之間的映射關系,在內存不足時,JVM會自動回收這些緩存圖片對象所占用的空間,從而有效地避免了OOM的問題.
通過軟引用實現Java對象的高速緩存:比如我們創建了一Person的類,如果每次需要查詢一個人的信息,哪怕是幾秒中之前剛剛查詢過的,都要重新構建一個實例,這將引起大量Person對象的消耗,并且由于這些對象的生命周期相對較短,會引起多次GC影響性能。此時,通過軟引用和 HashMap 的結合可以構建高速緩存,提供性能。
1.37. 對象的相等與指向他們的引用相等,兩者有什么不同?
對象的相等,比的是內存中存放的內容是否相等。而引用相等,比較的是他們指向的內存地址是否相等。
1.38. 什么是方法的返回值?返回值在類的方法里的作用是什么?
方法的返回值是指我們獲取到的某個方法體中的代碼執行后產生的結果!(前提是該方法可能產生結果)。返回值的作用:接收出結果,使得它可以用于其他的操作!
1.39. String 和 StringBuffer、StringBuilder 的區別是什么 String 為什么是不可變的
可變性
簡單的來說:String 類中使用 final 關鍵字字符數組保存字符串,private final char value[],所以 String 對象是不可變的。而StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數組保存字符串char[]value 但是沒有用 final 關鍵字修飾,所以這兩種對象都是可變的
線程安全性
String 中的對象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。StringBuilder 并沒有對方法進行加同步鎖,所以是非線程安全的。
性能
每次對 String 類型進行改變的時候,都會生成一個新的 String 對象,然后將指針指向新的 String 對象。StringBuffer 每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象并改變對象引用。相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。
對于三者使用的總結:
1.40. == 與 equals(重要)
== : 它的作用是判斷兩個對象的地址是不是相等。即,判斷兩個對象是不是同一個對象。(基本數據類型“= =”比較的是值,引用數據類型 = = 比較的是內存地址).
equals() : 它的作用也是判斷兩個對象是否相等。但它一般有兩種使用情況:
情況1:類沒有覆蓋 equals() 方法。則通過 equals() 比較該類的兩個對象時,等價于通過“==”比較這兩個對象。
情況2:類覆蓋了 equals() 方法。一般,我們都覆蓋 equals() 方法來兩個對象的內容相等;若它們的內容相等,則返回 true (即,認為這兩個對象相等)。
說明:
String 中的 equals 方法是被重寫過的,因為 object 的 equals 方法是比較的對象的內存地址,而 String 的 equals 方法比較的是對象的值。
當創建 String 類型的對象時,虛擬機會在常量池中查找有沒有已經存在的值和要創建的值相同的對象,如果有就把它賦給當前引用。如果沒有就在常量池中重新創建一個 String 對象。
1.41. hashCode 與 equals(重要)
面試官可能會問你:“你重寫過 hashcode 和 equals 么,為什么重寫equals時必須重寫hashCode方法?”
hashCode()介紹
hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數。
散列表存儲的是鍵值對(key-value),它的特點是:能根據“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!(可以快速找到所需要的對象)。
為什么要有 hashCode
我們以“HashSet 如何檢查重復”為例子來說明為什么要有 hashCode:
當你把對象加入 HashSet 時,HashSet 會先計算對象的 hashcode 值來判斷對象加入的位置,同時也會與其他已經加入的對象的 hashcode 值作比較,如果沒有相符的hashcode,HashSet會假設對象沒有重復出現。但是如果發現有相同 hashcode 值的對象,這時會調用 equals()方法來檢查 hashcode 相等的對象是否真的相同。如果兩者相同,HashSet 就不會讓其加入操作成功。如果不同的話,就會重新散列到其他位置。(摘自我的Java啟蒙書《Head fist java》第二版)。這樣我們就大大減少了 equals 的次數,相應就大大提高了執行速度。
hashCode()與equals()的相關規定
1.42. 簡述線程,程序、進程的基本概念。以及他們之間關系是什么?
1.43. 線程有哪些基本狀態?這些狀態是如何定義的?
(一). 等待阻塞:運行(running)的線程執行o.wait()方法,JVM會把該線程放 入等待隊列(waitting queue)中。
(二). 同步阻塞:運行(running)的線程在獲取對象的同步鎖時,若該同步鎖 被別的線程占用,則JVM會把該線程放入鎖池(lock pool)中。
(三). 其他阻塞: 運行(running)的線程執行Thread.sleep(long ms)或t.join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入可運行(runnable)狀態。
1.44.final, finally, finalize的區別
final
finally
finally 是用于異常處理的場面,無論是否有異常拋出,都會執行
finalize
finalize是Object的方法,所有類都繼承了該方法。 當一個對象滿足垃圾回收的條件,并且被回收的時候,其finalize()方法就會被調用
1.45. Java 中的異常處理
祖先java.lang包中的 Throwable類。Throwable: 有兩個重要的子類:Exception(異常) 和 Error(錯誤) ,二者都是 Java 異常處理的重要子類,各自都包含大量子類。
Error(錯誤):是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。例如,Java虛擬機運行錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的內存資源時,將出現 OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。
Exception(異常):是程序本身可以處理的異常。 Exception 類有一個重要的子類 RuntimeException。RuntimeException 異常由Java虛擬機拋出。NullPointerException(要訪問的變量沒有引用任何對象時,拋出該異常)、ArithmeticException(算術運算異常,一個整數除以0時,拋出該異常)和 ArrayIndexOutOfBoundsException (下標越界異常)。
Throwable類常用方法
1. public string getMessage():返回異常發生時的詳細信息
2. public string toString():返回異常發生時的簡要描述
3. public void printStackTrace():在控制臺上打印Throwable對象封裝的異常信息
異常處理總結
try 塊: 用于捕獲異常。其后可接零個或多個catch塊,如果沒有catch塊,則必須跟一個finally塊。
catch 塊:用于處理try捕獲到的異常。
finally 塊: 無論是否捕獲或處理異常,finally塊里的語句都會被執行。當在try塊或catch塊中遇到return語句時,finally語句塊將在方法返回之前被執行
在以下4種特殊情況下,finally塊不會被執行:
1.46. 說出最常見到的runtime exception與Error
error
1. OutOfMemoryError (堆內存溢出) 2. StackOverflowError(棧內存溢出)1.47 java中有幾種類型的流?
Java中所有的流都是基于字節流,所以最基本的流是 字節流
InputStream OutputStream
在字節流的基礎上,封裝了字符流
Reader Writer
進一步,又封裝了緩存流
BufferedReader PrintWriter
DataInputStream DataOutputStream
ObjectInputStream ObjectOutputStream
1.48. 獲取用鍵盤輸入常用的的兩種方法
方法1:通過 Scanner
Scanner input = new Scanner(System.in); String s = input.nextLine(); input.close();方法2:通過 BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String s = input.readLine();1.49. Java創建對象有幾種方式?
java中提供了以下四種創建對象的方式:
- new創建新對象
- 通過反射機制
- 采用clone機制
- 通過序列化機制
1.50. Java反射
編譯期和運行期,編譯期就是編譯器幫你把源代碼翻譯成機器能識別的代碼,比如編譯器把java代碼編譯成jvm識別的字節碼文件,而運行期指的是將可執行文件交給操作系統去執行,JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制
2. java反射(Reflection)的底層實現原理
Object 類,是所有Java 類的繼承根源,其內聲明了數個應該在所有Java 類中被改寫的方法:其中getClass()返回一個Class 對象
而這個Class 類十分特殊。它和一般類一樣繼承自Object,當一個class被加載,或當加載器(class loader)的defineClass()被JVM調用,JVM 便自動產生一個Class 對象。
這邊列了下Class類其中的方法
獲取公共構造器 getConstructors()
獲取所有構造器 getDeclaredConstructors()
獲取該類對象 newInstance()
獲取類名包含包路徑 getName()
獲取類名不包含包路徑 getSimpleName()
獲取類公共類型的所有屬性 getFields()
獲取類的所有屬性 getDeclaredFields()
獲取類公共類型的指定屬性 getField(String name)
獲取類全部類型的指定屬性 getDeclaredField(String name)
獲取類公共類型的方法 getMethods()
獲取類的所有方法 getDeclaredMethods()
獲得類的特定公共類型方法: getMethod(String name, Class[] parameterTypes)
獲取內部類 getDeclaredClasses()
獲取外部類 getDeclaringClass()
獲取修飾符 getModifiers()
獲取所在包 getPackage()
獲取所實現的接口 getInterfaces()
1.51. 反射中,Class.forName和classloader的區別。
java中class.forName()和classLoader都可用來對類進行加載。
class.forName()前者除了將類的.class文件加載到jvm中之外,還會對類進行解釋,執行類中的static塊。
而classLoader只干一件事情,就是將.class文件加載到jvm中,不會執行static中的內容,只有在newInstance才會去執行static塊。
1.52. 什么是序列化?序列化有什么好處。
1. 序列化是干什么的?
簡單說就是將內存中的對象保存下來,并且可以把保存的對象狀態再讀出來。
實現java序列化的手段是讓該類實現接口 Serializable,這個接口是一個標識性接口,沒有任何方法,僅僅用于表示該類可以序列化。
2. 什么情況下需要序列化
當你想把的內存中的對象保存到一個文件中或者數據庫中時候;
當你想用序列化在網絡上傳送對象的時候;
當你想通過RMI傳輸對象的時候;
a)當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable接口;
把一個對象完全轉成字節序列,方便傳輸。
就像你寄一箱餅干,因為體積太大,就全壓成粉末緊緊地一包寄出去,這就是序列化的作用。
只不過JAVA的序列化是可以完全還原的。
1.53. Java序列話中如果有些字段不想進行序列化 怎么辦?
對于不想進行序列化的變量,使用transient關鍵字修飾。
transient關鍵字的作用是:阻止實例中那些用此關鍵字修飾的的變量序列化;當對象被反序列化時,被transient修飾的變量值不會被持久化和恢復。transient只能修飾變量,不能修飾類和方法。
1.54. java拷貝
淺拷貝與深拷貝
看了很多文章,有些說淺拷貝只是拷貝引用地址,深拷貝才拷貝具體應用的對象,但經過LZ的核實發現有些文章個人感覺對拷貝的理解不是很正確。
總結了一下
淺拷貝
只復制一個對象與對象內部的基本類型,對象內部存在的指向其他對象數組或者引用則不復制
深拷貝
深拷貝:對象,對象內部的引用均復制
拷貝的幾種方法
- System.arraycopy(淺拷貝)
- Arrays.copyOf(淺拷貝)
實際上它調用的就是System.arraycopy. - Object.clone
clone()比較特殊,對于對象而言,它是深拷貝,但是對于數組而言,它是淺拷貝。
(二)基礎相關面試題
2.1. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round 的意思是+0.5 取整數
所以 Math.round(11.5) 即 11.5+0.5 = 12
Math.round(-11.5) 即 -11.5+0.5 = -11
2.2. String s = new String(“xyz”);創建了幾個String Object?
String s = new String(“xyz”);
首先構造方法 new String(“xyz”); 中的"xyz" 這本身就是一個字符串對象
然后 new 關鍵字一定會創建一個對象
所以總共創建了兩個String對象
2.3. &和&&的區別
& 和 && 分別表示長路與和短路與
長路:兩側,都會被運算
短路: 只要第一個是false,第二個就不進行運算了
2.4. 以下代碼會輸出什么
題1
public class Main {public static void main(String[] args) {Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1==i2);System.out.println(i3==i4);} }運行結果為 true false
原因:輸出結果表明i1和i2指向的是同一個對象,而i3和i4指向的是不同的對象 ,Integer的緩沖池如果數值在[-128,127]之間直接是從緩沖池中取得,所以是同一個對象。
題2:
public class Main {public static void main(String[] args) {Double i1 = 100.0;Double i2 = 100.0;Double i3 = 200.0;Double i4 = 200.0;System.out.println(i1==i2);System.out.println(i3==i4);} }運行結果為 false false
原因: 在某個范圍內的整型數值的個數是有限的,而浮點數卻不是,故每個double對象指向一個新的地址。
2.5. 3*0.1 == 0.3返回值是什么?
返回結果為false,因為浮點數不能完全精確的表示出來,在計算機中浮點數的表示是誤差的。所以一般情況下不進行兩個浮點數是否相同的比較。
2.6. a=a+b與a+=b有什么區別嗎?
以下代碼是否有錯,有的話怎么改?
short s1= 1; s1 = s1 + 1;有錯誤.short類型在進行運算時會自動提升為int類型,也就是說 s1+1 的運算結果是int類型,而s1是
short類型,此時編譯器會報錯
正確寫法:
short s1= 1; s1 += 1;結論:+= 操作符會進行隱式自動類型轉換,此處a+=b隱式的將加操作的結果類型強制轉換為持有結果的類
型,而a=a+b則不會自動進行類型轉換.
2.7 try catch finally,try里有return,finally還執行么?
執行,并且finally的執行早于try里面的return
2.8 說說你平時是怎么處理 Java 異常的
使用 try-catch-finally
- try 塊負責監控可能出現異常的代碼
- catch 塊負責捕獲可能出現的異常,并進行處理
- finally塊負責清理各種資源,不管是否出現異常都會執行
- 其中 try 塊是必須的,catch 和 finally 至少存在一個標準異常處理流程
版權聲明:本文為博主原創文章,未經博主允許不得轉載
https://blog.csdn.net/qq_44614710/article/details/113698325
總結
以上是生活随笔為你收集整理的java面试题-基础篇(万字总结,带答案,面试官问烂,跳槽必备)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 同时获取同一等级下多个class值的节点
- 下一篇: scrapy框架-post使用