Java你可能不知道的事系列1


概述

本類文章會不段更新分析學習到的經典面試題目,在此記錄下來便於自己理解。如果有不對的地方還請各位觀眾拍磚。
今天主要分享一下常用的字符串的幾個題目,相信學習java的小伙伴們對String類是再熟悉不過了,今天我們就來和她再次邂逅,好了下面開始。

先來說說String特點

String是不可變的常量,每當我們創建一個字符串對象的時候,如果堆區的常量池里不存在這個字符串,就會創建一個存儲在常量池里(String存的地方叫String pool),如果存在了,就直接把變量的地址指向常量池里,比如:String b = “abc” 這句話 內存表示如下。下面開始上題
這里寫圖片描述

1.1

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2);

輸出結果是什么呢?
從上面的圖也大概說了jvm里面有棧區、堆區。棧區里面主要存放的是局部變量,堆區里存放的是new出來的對象。==對於對象類型比較的是地址。所以在s1和s1是分別引用了堆里面new出來的不同對象的地址,圖形理解如下

這里寫圖片描述

答案很明顯了,地址不同 輸出false.

1.2

String s1 = "abc";
StringBuffer s2 = new StringBuffer(s1);
System.out.println(s1.equals(s2));

這是true 還是false呢?答案是false。

首先s1變量引用了字符串”abc”,然后StringBuffer s2 = new StringBuffer(s1),新建了一個StringBuffer對象調用append()方法返回自身。調用String的equals方法。重點就是這個equals方法里有個instance of,必需是同一類型的才進行比較否則直接返回false。
來看一下源碼:

/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
//關鍵點就在這里了
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

1.3

下面的代碼在內存會產生幾個對象呢?
String s1 = new String(“abc”);
String s2 = new String(“abc”);

答案:3個
有了上面的分析,相信大家都明白了,new了兩個對象,加上string pool里的一個”abc”。

1.4

下面的代碼輸出結果是啥?

String s1 = "abc";
String s2 = new String("abc");
s2.intern();
System.out.println(s1 ==s2);

我們可能對intern()這個方法不太熟悉,先來看看注釋:

/**
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class <code>String</code>.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this <code>String</code> object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this <code>String</code> object is added to the
* pool and a reference to this <code>String</code> object is returned.
* <p>
* It follows that for any two strings <code>s</code> and <code>t</code>,
* <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
* if and only if <code>s.equals(t)</code> is <code>true</code>.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* <cite>The Java&trade; Language Specification</cite>.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*/
public native String intern();

注釋好多我草,關鍵的是這句:When the intern method is invoked, if the pool already contains a string equal to this String object as determined by
the {@link #equals(Object)} method, then the string from the pool is
returned. Otherwise, this String object is added to the
pool and a reference to this String object is returned.
大致就是說,如果常量池里不存在這個字符串,就創建一個並且返回地址,否則的話直接返回地址。

上面的代碼第二行String s2 = new String(“abc”); s2其實是引用到了new的對象,雖然在第三行調用了intern方法,但是沒有賦值給s2,所以s2的引用還是沒有變。所以返回false。
如果第三行代碼改成s2 = s2.intern()就會返回true了。

 String s1 = "abc";
String s2 = new String("abc");
s2 = s2.intern();
System.out.println(s1==s2);

好了,今天就到這里。之后會繼續分析。如果喜歡我的文章歡迎關注我。各位看官大爺的支持是我最大的動力!!


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: