String
文章目錄
- String
- 一、創建字串
- 二、字串比較相等
- 2.1equals
- 三、字串常量池
- 3.1 Intern()方法
- 3.2 注意事項
- 四、理解字串不可變
- 五、StringBuffer 和 StringBuilder
- 5.1String與StringBuffer 和 StringBuilder的區別
- 5.2 StringBuffer和StringBuilder的區別
前言:java的學習整理:
一、初階前言 javaSe
二、初階認識javaSE,資料型別與運算子
三、java初識:類和物件
四、javaSE 【面向物件編程】初階 多型、抽象類、介面
一、創建字串
有三種方式:
//第一種:
String str="hello";
System.out.println(str);
//第二種:
String str1=new String("baba");
System.out.println(str1);
前面兩種都是參考型別,那為什么沒有toString方法尼?
參考型別重寫toString方法:toString() 方法可把一個 Number 物件轉換為一個字串,并回傳結果,
在String底層就有toString方法

回傳是this,this所指向了System.out.println,在println底層是已經寫好了怎么該怎么列印物件類里面的內容,

//第三種:
char[] ch={'a','b','c'};
String str3=new String(ch);
System.out.println(str3);

第三種方法的底層實作如圖所示,不在贅述,
二、字串比較相等
直接上代碼
public static void main(String[] args) {
String str="hello";
String str2="hello";
System.out.println(str==str2);
}
大家看看運行結果會是什么尼?————————沒錯就是true!!!,就是這么簡單,
那我們再看下一個代碼:
public static void main(String[] args) {
String str=new String("hello");
String str2=new String("hello");
System.out.println(str==str2);
}
大家覺得這個運行結果是什么尼??——————沒錯運行出來就是false,就是這么的坑,看圖解釋吧,

new了str和str2,就是在堆上開辟了兩個空間來存盤hello,也就是記憶體中存在兩份hello,
String使用==比較并不是在比較字串里的內容,而是比較兩個參考是否指向同一個物件,
Java 中要想比較字串的內容, 必須采用String類提供的equals方法
public static void main(String[] args) {
String str=new String("hello");
String str2=new String("hello");
System.out.println(str.equals(str2));
}
這樣運行的結果就是true了,
2.1equals
是用來比較兩個字串的內容是否相等
但他也有注意事項:
有兩種比較方式;
//方式一
String str=new String("hello");
System.out.println("hello".equals(str));
//方式二
System.out.println(str.equals("hello"));
兩種方法都可以比較,但是那種最優尼??
跟推薦方式一,一點str為null,方式二就會報出NullPointerException,所以方式一更安全,
三、字串常量池
上代碼舉例
public static void main(String[] args) {
String str="hello";
String str2=new String("hello");
System.out.println(str==str2);
}
大家看看這段代碼,就不猜了,運行結果是false,上圖理解

在上面說過String==比較的是兩個參考是否指向同一個物件,圖上很明顯指向的都是,不同的物件,所以是fales,同時也引出了字串常量池概念,
字串常量池是存放在堆里的一塊記憶體,里面存的是String類的物件實體化操作 用雙引號里面的內容,如果里面放入多個同樣的內容,則舍去多余的,只留下一個,這樣也節約了記憶體空間,
為加深印象再多看看代碼:
public static void main(String[] args) {
String str="co2";
String str2="co2o2";
String str3=str+"o2";
System.out.println(str2==str3);
}

看圖可知所以是false,
public static void main(String[] args) {
String str="co2o2";
String str2=new String("co2")+new String("o2");
System.out.println(str==str2);
}
運行結果:false

3.1 Intern()方法
intern()方法的作用
一、如果SCP(字串常量池)中存在A內容一樣的字串物件C,就回傳C
二、否則,將A 加入到SCP中,回傳A
上代碼:
public static void main(String[] args) {
String str="co2o2";
String str2=new String("co2o2");
str.intern();
System.out.println(str==str2);
}

intern()方法常量池中有相同的內容,則回傳存在的內容,但是str還是指向的另一個物件,所以為false,
再來看一個復雜一點的代碼:
public static void main(String[] args) {
String str=new String("2")+new String("2");
str.intern();
String str2="22";
System.out.println(str==str2);
}

看圖可知最后指的都是同一個物件,所以運行結果是true.
3.2 注意事項
public static void main(String[] args) {
String str="hello";
String str2=str;
str="world";
System.out.println(str==str2);
}
傳的是參考
再來看看復雜點的代碼:
public static void func(String str) {
str="haha";
}
public static void main(String[] args) {
String str="hello";
func(str);
System.out.println(str);
}

上圖是傳參考只是改變方向,改變內容是通過這個參考修改他指向的這個物件,
再看一個代碼:
public class Test {
String str = new String("good");
char[ ] ch = { 'a' , 'b' , 'c' };
public static void main(String args[]){
Test ex = new Test();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str,char ch[ ]){
str = "test ok";
ch[0] = 'g';
}
}

這段代碼和影像更好的解釋了參考可以改變方向,但是不改變里面的內容,里面的str只是改變了參考就沒有改變里面的內容,陣列ch通過了這個參考修改他指向的這個物件,
回顧參考:
參考相當于一個指標, 里面存的內容是一個地址. 我們要區分清楚當前修改到底是修改了地址對應記憶體的內容發生改變了, 還是參考中存的地址改變了
四、理解字串不可變
還是先看代碼
public static void main(String[] args) {
String str = "hello" ;//不可變
str = str + " world" ;
str += " !!!" ;
System.out.println(str);
}

通過代碼和圖,可以看出String的物件是不可變的,本身不會發生變化,str卻參考了多個其他物件,他不會直接在hello后面直接+world !!!,而是創建多個物件,最后多個物件拼接而成為hello world !!!,
五、StringBuffer 和 StringBuilder
5.1String與StringBuffer 和 StringBuilder的區別
盡然StringBuffer和StringBuilder前面都有String,那么肯定跟String脫不了關系,先來說說他們的區別,看代碼:
public static void main(String[] args) {
String str="hello";
StringBuffer str2="haha";//這么寫編譯器會報錯
StringBuilder str3="lala";//這么寫編譯器會報錯
}
public static void main(String[] args) {
StringBuffer str2=new StringBuffer("haha");
StringBuilder str3=new StringBuilder("lala");
//這么寫編譯器才能通過
}
所以引出了第一個區別,String可以直接賦值和用構造方法,而StingBuffer和StringBuilder只能通過構造方法賦值,
第二個區別:
public static void main(String[] args) {
StringBuffer str2=new StringBuffer();
str2.append(" hello").append(" haha");
System.out.println(str2);
String str="hello"+"haha";
//System.out.println(str);
}
根據代碼也可看出String是以+號鏈接,StringBuffer和StringBuilder是通過append()方法鏈接.
第三個區別
public static void main(String[] args) {
StringBuffer str2=new StringBuffer();
str2.append(" hello").append(" haha");
System.out.println(str2);
System.out.println(str2.reverse());
String str="hello"+"haha";
//System.out.println(str);
}
String功能有的,StringBuffer和StringBuilder都有,但是StringBuffer和StringBuilder功能有的,String沒有,就如上面的代碼,StringBuffer和StringBuilder有reverse()方法,用起來比較方便
我們再深層次的了解下String

通過反編譯可以了解到右上角的代碼底層是怎么實作的,先是new了一個StringBulider物件,然后空的構造方法,再是呼叫append()方法,最后是toString()方法,也就是說可以寫成下面的代碼:
public static void main(String[] args) {
StringBuilder str=new StringBuilder();
str.append("hello").append(" haha").toString();
System.out.println(str);
}
通過底層我們發現代碼被優化了,那么為什么會被優化尼??

由圖可知被優化后,只會在new這個物件里進行改變,不會一直創建新的物件,
所以說String是不可變的,StringBuilder是可變的
5.2 StringBuffer和StringBuilder的區別

由圖可知StringBuffer前面有一個sunchronized修飾,代表保證執行緒安全的,適合于多執行緒,而沒有Synchronized修飾適合單執行緒情況,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/303034.html
標籤:java
