可變性 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類利用了final修飾的char類型數組存儲字符,源碼以下圖因此:編程
/** The value is used for character storage. */
private final char value[];
複製代碼
我以爲若是別人問這個問題的話,回答不可變就能夠了。 下面只是給你們看兩個有表明性的例子: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語言的反射機制。
反射是框架設計的靈魂。
在咱們平時的項目開發過程當中,基本上不多會直接使用到反射機制,但這不能說明反射機制沒有用,實際上有不少設計、開發都與反射機制有關,例如模塊化的開發,經過反射去調用對應的字節碼;動態代理設計模式也採用了反射機制,還有咱們平常使用的 Spring/Hibernate 等框架也大量使用到了反射機制。
舉例:①咱們在使用JDBC鏈接數據庫時使用Class.forName()經過反射加載數據庫的驅動程序;②Spring框架也用到不少反射機制,最經典的就是xml的配置模式。Spring 經過 XML 配置模式裝載 Bean 的過程:1) 將程序內全部 XML 或 Properties 配置文件加載入內存中; 2)Java類裏面解析xml或properties裏面的內容,獲得對應實體類的字節碼字符串以及相關的屬性信息; 3)使用反射機制,根據這個字符串得到某個類的Class實例; 4)動態配置實例的屬性
推薦閱讀:
這幾個是Java中很基本很基本的東西,可是我相信必定還有不少人搞不清楚!爲何呢?由於咱們大多數時候在使用現成的編譯工具以及環境的時候,並無去考慮這些東西。
JDK: 顧名思義它是給開發者提供的開發工具箱,是給程序開發者用的。它除了包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其餘供開發者使用的工具包。
JRE: 普通用戶而只須要安裝JRE(Java Runtime Environment)來運行Java程序。而程序開發者必須安裝JDK來編譯、調試程序。
JVM: 當咱們運行一個程序時,JVM負責將字節碼轉換爲特定機器代碼,JVM提供了內存管理/垃圾回收和安全機制等。這種獨立於硬件和操做系統,正是java程序能夠一次編寫多處執行的緣由。
區別與聯繫:
先看下java中的編譯器和解釋器:
Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這臺虛擬的機器在任何平臺上都提供給編譯程序一個的共同的接口。編譯程序只須要面向虛擬機,生成虛擬機可以理解的代碼,而後由解釋器來將虛擬機代碼轉換爲特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫作字節碼
(即擴展名爲.class
的文件),它不面向任何特定的處理器,只面向虛擬機。每一種平臺的解釋器是不一樣的,可是實現的虛擬機是相同的。Java源程序通過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,而後在特定的機器上運行。這也就是解釋了Java的編譯與解釋並存的特色。
Java源代碼---->編譯器---->jvm可執行的Java字節碼(即虛擬指令)---->jvm---->jvm中解釋器----->機器可執行的二進制機器碼---->程序運行。
採用字節碼的好處:
Java語言經過字節碼的方式,在必定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特色。因此Java程序運行時比較高效,並且,因爲字節碼並不專對一種特定的機器,所以,Java程序無須從新編譯即可在多種不一樣的計算機上運行。
我知道不少人沒學過C++,可是面試官就是沒事喜歡拿我們Java和C++比呀!沒辦法!!!就算沒學過C++,也要記下來!
重載: 發生在同一個類中,方法名必須相同,參數類型不一樣、個數不一樣、順序不一樣,方法返回值和訪問修飾符能夠不一樣,發生在編譯時。
重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;若是父類方法訪問修飾符爲private則子類就不能重寫該方法。
Java-Guide: Java面試通關手冊(Java學習指南)Java Interview Customs Manual (Java Study Guide)。star:1.9k。
Github地址:github.com/Snailclimb/…
文檔定位:一個專門爲Java後端工程師準備的開源文檔,相信不論你是Java新手仍是已經成爲一名Java工程師都能從這份文檔中收穫到一些東西。
參考:
你若怒放,清風自來。 歡迎關注個人微信公衆號:「Java面試通關手冊」,一個有溫度的微信公衆號。公衆號有大量資料,回覆關鍵字「1」你可能看到想要的東西哦!