最最最多見的Java面試題總結——第二週

String和StringBuffer、StringBuilder的區別是什麼?String爲何是不可變的?

String和StringBuffer、StringBuilder的區別

可變性   String類中使用字符數組:private final char value[]保存字符串,因此String對象是不可變的。StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[]value,這兩種對象都是可變的。   java

線程安全性git

String中的對象是不可變的,也就能夠理解爲常量,線程安全。AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操做,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。StringBuilder並無對方法進行加同步鎖,因此是非線程安全的。   程序員

性能github

每次對String 類型進行改變的時候,都會生成一個新的String對象,而後將指針指向新的String 對象。StringBuffer每次都會對StringBuffer對象自己進行操做,而不是生成新的對象並改變對象引用。相同狀況下使用StirngBuilder 相比使用StringBuffer 僅能得到10%~15% 左右的性能提高,但卻要冒多線程不安全的風險。面試

對於三者使用的總結:數據庫

  • 若是要操做少許的數據用 = String
  • 單線程操做字符串緩衝區 下操做大量數據 = StringBuilder
  • 多線程操做字符串緩衝區 下操做大量數據 = StringBuffer

String爲何是不可變的嗎?

簡單來講就是String類利用了final修飾的char類型數組存儲字符,源碼以下圖因此:編程

/** The value is used for character storage. */
    private final char value[];
複製代碼

String真的是不可變的嗎?

我以爲若是別人問這個問題的話,回答不可變就能夠了。 下面只是給你們看兩個有表明性的例子:segmentfault

1) String不可變但不表明引用不能夠變後端

String str = "Hello";
		str = str + " World";
		System.out.println("str=" + str);
複製代碼

結果:設計模式

str=Hello World
複製代碼

解析:

實際上,原來String的內容是不變的,只是str由原來指向"Hello"的內存地址轉爲指向"Hello World"的內存地址而已,也就是說多開闢了一塊內存區域給"Hello World"字符串。

2) 經過反射是能夠修改所謂的「不可變」對象

// 建立字符串"Hello World", 並賦給引用s
		String s = "Hello World";

		System.out.println("s = " + s); // Hello World

		// 獲取String類中的value字段
		Field valueFieldOfString = String.class.getDeclaredField("value");

		// 改變value屬性的訪問權限
		valueFieldOfString.setAccessible(true);

		// 獲取s對象上的value屬性的值
		char[] value = (char[]) valueFieldOfString.get(s);

		// 改變value所引用的數組中的第5個字符
		value[5] = '_';

		System.out.println("s = " + s); // Hello_World
複製代碼

結果:

s = Hello World
s = Hello_World
複製代碼

解析:

用反射能夠訪問私有成員, 而後反射出String對象中的value屬性, 進而改變經過得到的value引用改變數組的結構。可是通常咱們不會這麼作,這裏只是簡單提一下有這個東西。

什麼是反射機制?反射機制的應用場景有哪些?

反射機制介紹

JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。

靜態編譯和動態編譯

  • **靜態編譯:**在編譯時肯定類型,綁定對象
  • **動態編譯:**運行時肯定類型,綁定對象

反射機制優缺點

  • 優勢: 運行期類型的判斷,動態加載類,提升代碼靈活度。
  • 缺點: 性能瓶頸:反射至關於一系列解釋操做,通知 JVM 要作的事情,性能比直接的java代碼要慢不少。

反射的應用場景

反射是框架設計的靈魂。

在咱們平時的項目開發過程當中,基本上不多會直接使用到反射機制,但這不能說明反射機制沒有用,實際上有不少設計、開發都與反射機制有關,例如模塊化的開發,經過反射去調用對應的字節碼;動態代理設計模式也採用了反射機制,還有咱們平常使用的 Spring/Hibernate 等框架也大量使用到了反射機制。

舉例:①咱們在使用JDBC鏈接數據庫時使用Class.forName()經過反射加載數據庫的驅動程序;②Spring框架也用到不少反射機制,最經典的就是xml的配置模式。Spring 經過 XML 配置模式裝載 Bean 的過程:1) 將程序內全部 XML 或 Properties 配置文件加載入內存中; 2)Java類裏面解析xml或properties裏面的內容,獲得對應實體類的字節碼字符串以及相關的屬性信息; 3)使用反射機制,根據這個字符串得到某個類的Class實例; 4)動態配置實例的屬性

推薦閱讀:

什麼是JDK?什麼是JRE?什麼是JVM?三者之間的聯繫與區別

這幾個是Java中很基本很基本的東西,可是我相信必定還有不少人搞不清楚!爲何呢?由於咱們大多數時候在使用現成的編譯工具以及環境的時候,並無去考慮這些東西。

JDK: 顧名思義它是給開發者提供的開發工具箱,是給程序開發者用的。它除了包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其餘供開發者使用的工具包。

JRE: 普通用戶而只須要安裝JRE(Java Runtime Environment)來運行Java程序。而程序開發者必須安裝JDK來編譯、調試程序。

JVM: 當咱們運行一個程序時,JVM負責將字節碼轉換爲特定機器代碼,JVM提供了內存管理/垃圾回收和安全機制等。這種獨立於硬件和操做系統,正是java程序能夠一次編寫多處執行的緣由。

區別與聯繫:

  1. JDK用於開發,JRE用於運行java程序 ;
  2. JDK和JRE中都包含JVM ;
  3. JVM是java編程語言的核心而且具備平臺獨立性。

什麼是字節碼?採用字節碼的最大好處是什麼?

先看下java中的編譯器和解釋器:   

Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這臺虛擬的機器在任何平臺上都提供給編譯程序一個的共同的接口。編譯程序只須要面向虛擬機,生成虛擬機可以理解的代碼,而後由解釋器來將虛擬機代碼轉換爲特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫作字節碼(即擴展名爲.class的文件),它不面向任何特定的處理器,只面向虛擬機。每一種平臺的解釋器是不一樣的,可是實現的虛擬機是相同的。Java源程序通過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,而後在特定的機器上運行。這也就是解釋了Java的編譯與解釋並存的特色。

Java源代碼---->編譯器---->jvm可執行的Java字節碼(即虛擬指令)---->jvm---->jvm中解釋器----->機器可執行的二進制機器碼---->程序運行。

採用字節碼的好處:   

Java語言經過字節碼的方式,在必定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特色。因此Java程序運行時比較高效,並且,因爲字節碼並不專對一種特定的機器,所以,Java程序無須從新編譯即可在多種不一樣的計算機上運行。

Java和C++的區別

我知道不少人沒學過C++,可是面試官就是沒事喜歡拿我們Java和C++比呀!沒辦法!!!就算沒學過C++,也要記下來!

  • 都是面向對象的語言,都支持封裝、繼承和多態
  • Java不提供指針來直接訪問內存,程序內存更加安全
  • Java的類是單繼承的,C++支持多重繼承;雖然Java的類不能夠多繼承,可是接口能夠多繼承。
  • Java有自動內存管理機制,不須要程序員手動釋放無用內存

接口和抽象類的區別是什麼?

  1. 接口的方法默認是public,全部方法在接口中不能有實現,抽象類能夠有非抽象的方法
  2. 接口中的實例變量默認是final類型的,而抽象類中則不必定
  3. 一個類能夠實現多個接口,但最多隻能實現一個抽象類
  4. 一個類實現接口的話要實現接口的全部方法,而抽象類不必定
  5. 接口不能用new實例化,但能夠聲明,可是必須引用一個實現該接口的對象 從設計層面來講,抽象是對類的抽象,是一種模板設計,接口是行爲的抽象,是一種行爲的規範。

成員變量與局部變量的區別有那些?

  1. 從語法形式上,當作員變量是屬於類的,而局部變量是在方法中定義的變量或是方法的參數;成員變量能夠被public,private,static等修飾符所修飾,而局部變量不能被訪問控制修飾符及static所修飾;可是,成員變量和局部變量都能被final所修飾;
  2. 從變量在內存中的存儲方式來看,成員變量是對象的一部分,而對象存在於堆內存,局部變量存在於棧內存
  3. 從變量在內存中的生存時間上看,成員變量是對象的一部分,它隨着對象的建立而存在,而局部變量隨着方法的調用而自動消失。
  4. 成員變量若是沒有被賦初值,則會自動以類型的默認值而賦值(一種狀況例外被final修飾但沒有被static修飾的成員變量必須顯示地賦值);而局部變量則不會自動賦值。

重載和重寫的區別

重載: 發生在同一個類中,方法名必須相同,參數類型不一樣、個數不一樣、順序不一樣,方法返回值和訪問修飾符能夠不一樣,發生在編譯時。   

重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;若是父類方法訪問修飾符爲private則子類就不能重寫該方法。

字符型常量和字符串常量的區別

  1. 形式上: 字符常量是單引號引發的一個字符 字符串常量是雙引號引發的若干個字符
  2. 含義上: 字符常量至關於一個整形值(ASCII值),能夠參加表達式運算 字符串常量表明一個地址值(該字符串在內存中存放位置)
  3. 佔內存大小 字符常量只佔一個字節 字符串常量佔若干個字節(至少一個字符結束標誌)

寫在最後

開源文檔推薦

Java-Guide: Java面試通關手冊(Java學習指南)Java Interview Customs Manual (Java Study Guide)。star:1.9k。

Github地址:github.com/Snailclimb/…

文檔定位:一個專門爲Java後端工程師準備的開源文檔,相信不論你是Java新手仍是已經成爲一名Java工程師都能從這份文檔中收穫到一些東西。

參考:

segmentfault.com/a/119000001…

blog.csdn.net/sinat_38259…

你若怒放,清風自來。 歡迎關注個人微信公衆號:「Java面試通關手冊」,一個有溫度的微信公衆號。公衆號有大量資料,回覆關鍵字「1」你可能看到想要的東西哦!

相關文章
相關標籤/搜索