一道關於String的面試題,新鮮出爐,剛被坑過,趁熱!!

不少人都會答錯的一道關於String的題目,究竟有什麼難度?

咱們一塊兒來看一道關於String的面試題,準確說是改編的面試題!

  準備好啦?在放大招以前先來一個小招式java

String s1 = new String("hello");
String s2 = new String("hello");

來,問你們,在這一小段代碼中一共建立了幾個對象呢?面試

其實這道題並不難,考察的是關於String的重點知識點常量池和字符串優化。數組

這個是經典題了,答案是3個,由於這裏的「hello」會在字符串常量池中建立一個,而後在堆中建立2個,因此這道題的答案一共是建立了三個對象。函數

不過我以爲更加嚴謹的一點說法是應該判斷在字符串常量池中是否已經存在「hello」這個字符串,不過從這道題的本意來看,事先在字符串常量池中是不存在這個「hello」這個字符串的。優化

再來放一個小招式spa

 1 public class TestString {
 2     public static void main(String[] args) {
 3 
 4         String s1 = "Java";
 5         String s2 = "從0到1";
 6         String s3 = s1 + s2;
 7         String s4 = "Java從0到1";
 8 
 9         System.out.println(s3 == s4);
10 
11 
12     }
13 }

對於字符串常量池的位置,字符串常量池在jdk1.6及以前在方法區中,可是在jdk1.7及之後就放在了堆中,咱們如今通常不多使用jdk1.6及以前的版本,所以如今討論所說的字符串常量池除非特別說明jdk版本,不然默認是在堆中。code

另外對於字符串常量池中存放的是字符串對象,好比String a = 「abc」那麼在字符串常量池中就存放着這個abc,而這個abc則是一個字符串對象。

對象

哈哈哈,是否是已經開始懵了!blog

經過上面那兩題,咱們來悄悄的總結一下接口

1.編譯階段肯定的字符串纔會被放到字符串常量池中

2.字符串常量池在堆中

把第二段代碼細講一下吧

咱們知道s1和s2還有s4都會在字符串常量池中,這已經有三個對象了,關鍵的分析點在這行代碼上

 1 String s3 = s1 + s2; 


對於s3沒法在編譯階段肯定下來,因此不管最後的字符串是什麼都不會存在字符串常量池中,那麼存在哪呢?由於對象建立在堆中,而字符串常量池也在堆中,既然不在字符串常量池中那就是在字符串常量池以外的堆中了,而s3最終的字符串對象是「Java從0到1」,那麼也就是說這個字符串在常量池以外的堆中,這是一個對象了,加上以前的三個,這裏一共四個了,可是咱們還要分析這個s3是怎麼來的,是經過s1和s2相加獲得的,由於這個s3最終是在常量池以外的堆中造成的,而s1和s2都是在常量池中,所以會將s1和s2拷貝一份到字符串常量池以外的堆中來造成s3,咱們看下面的一張圖來加深理解

因此,這道題的答案是一共建立了6個對象,這道題常常做爲公司的面試題,爲此還有很多人被絆倒呢

 

大魔王還找了另一題,一樣也是關於String的面試題

程序以下:

 1 public class test8 {
 2 
 3     String str = new String("good");
 4     char[] ch = { 'a', 'b', 'c' };
 5 
 6     public static void main(String args[]){ 
 7         test8 ex=new test8(); 
 8         ex.change(ex.str,ex.ch); 
 9         System.out.print(ex.str+" and ");
10         for(int i=0;i<ex.ch.length;i++) {
11             System.out.println(ex.ch[i]);
12             }
13         }
14     public void change(String str,char ch[]){ 
15         str="test ok"; 
16         ch[0]='g';
17         }
18 
19 }

解析:
這是java參數傳遞方式的問題,Java參數,不論是原始類型仍是引用類型,傳遞的都是副本。
若是參數類型是原始類型,那麼傳過來的就是這個參數的一個副本,也就是這個原始參數的值。若是在函數中改變了副本的 值不會改變原始的值。
若是參數類型是引用類型,那麼傳過來的就是這個引用參數的副本,這個副本存放的是參數的地址。若是在函數中沒有改變這個副本的地址,而是改變了地址中的 值,那麼在函數內的改變會影響到傳入的參數。
a.傳遞值的數據類型:八種基本數據類型和String(這樣理解能夠,可是事實上String也是傳遞的地址,只是string對象和其餘對 象是不一樣的,string對象是不能被改變的,內容改變就會產生新對象。那麼StringBuffer就能夠了,但只是改變其內容。不能改變外部變量所指 向的內存地址)。
b.傳遞地址值的數據類型:除String之外的全部複合數據類型,包括數組、類和接口

ps: String 是 final 的。因此值是不變的。 函數中String對象引用的副本指向了另一個新String對象,而數組對象引用的副本沒有改變,而是改變對象中數據的內容.

相關文章
相關標籤/搜索