java有string这个类型吗_关于java的String类型
String類型的不可變
眾所周知,String類型是不可變的,一旦String對象被創建好了則這個字符串中的序列就不可改變。
為什么String類型是不可變?
根據閱讀源碼可知,String類是一個final類,但是String不可變并不是因為它是一個final類,final修飾的類只是不能被繼承,因為有字符串常量池這個東西,如果String類能被繼承就會出現安全問題。關于String不可變的原因是因為下面這句代碼:
private final char value[];
value負責存儲String的值,因為value是用final修飾的,所以value的地址不能被改變(但是數組的值可以被改變),又因為在String類中并沒有任何方法能夠修改value的元素,所以String是不可變的。但是在有的時候我們認為字符串改變了啊,例如String s="hi"; s+=" world";s輸出就會變成"hi world",這是因為重新給了s一個字符串對象,相加后的對象和以前的對象不一樣,后面將會有代碼演示。
String類型真的不可變嗎?
因為value是一個char數組,他只是地址不可變,其中的值是可變的,String不可變是因為它沒有提供給我們可以修改value的方法,但是我們可以通過反射獲取到value數組,然后修改它的值,這樣可以實現“String的可變”。如下代碼所示:
String s1= "hello world";
String s2 ="hello world";
System.out.println(s1==s2);
System.out.println(s1);
System.out.println(s2);
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[])field.get(s1);
value[1]='i';
value[2]='i';
value[3]='i';
value[4]='i';
System.out.println(s1==s2);
System.out.println(s1);
System.out.println(s2);
輸出結果
true
hello world
hello world
true
hiiii world
hiiii world
通過上面可以看出當我們改變s1的值時s2被改變了。
關于String的一些常識
如下代碼
String s1 = "hello world";
String s2 = "hello world";
String s3 = "hello "+"world";
String s4 = new String("hello world");
String s5 = "hello" + new String("world");
String s6 = new String("hello ");
String s7="world";
String s8 ="hello ";
String s9=s6+s7;
String s10=s8+s7;
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s1==s4);
System.out.println(s1==s5);
System.out.println(s4==s5);
System.out.println(s1==s9);
System.out.println(s1==s10);
System.out.println(s9==s10);
s1 = s1+"!";
System.out.println(s1);
System.out.println(s2);
System.out.println(s1==s2);
輸出結果
true
true
false
false
false
false
false
false
hello world!
hello world
false
在String中使用new就新創建一個對象,不論字符串常量池是否有它,而s3和s10的區別在于,在編譯階段就能確定s3,因為s3指定了是"hello "和"world"相結合,而s10在編譯階段程序并不能確定s8和s7的值。
String一些方法可能產生新的對象
subString
當subString截取的字符串就是本身的時候,返回本身,否則返回一個新聲明的字符串。
replace
如果新字符和要替換的一樣的話,返回本身,否則返回一個新聲明的字符串。
toCharArray
返回一個新的字符數組,對改數組進行修改不會對String產生任何影響。
toString
返回的是字符串本身
trim
trim方法是返回String對象的一個副本,該副本去除了原來字符串中的首部和尾部空白。但如果String對象首部和尾部沒有空白的話,則返回自身。否則調用subString方法返回一個嶄新的String對象(真子串,subString方法中說過)。
關于String傳參
在開始String傳參的時候先看看參數傳遞的兩大類型:
值傳遞:在我們進行參數傳遞的時候將實參拷貝一份傳遞過去,所以在方法里面對其更改不會對原本的造成影響。
引用傳遞:在java中引用傳遞是拷貝該對象的地址傳遞過去,如果在傳遞過去的地址對應的對象上進行修改就會影響原本的值。
具體例子如下:
//自己聲明的一個類
class Ref {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName(){
return name;
}
@Override
public String toString() {
return "Ref{" +
"name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
Ref ref = new Ref();
ref.setName("張三");
int a=5;
String name = "張三";
change(ref);
change(a);
change(name);
System.out.println(ref);
System.out.println(a);
System.out.println(name);
}
public static void change(Ref ref) {
ref.setName("李四");
}
public static void change(int num) {
num = 18;
}
public static void change(String name) {
name = "李四";
}
//上面輸出
/*
Ref{name='李四'}
5
張三
*/
//將ref 的change函數改變如下
public static void change(Ref ref) {
Ref ref1 = new Ref();
ref = ref1;
ref.setName("李四");
}
/*運行
Ref{name='張三'}
5
張三
*/
通過上面的例子我們發現對象的傳遞如果在方法里面進行了修改將會改變原本的值。但是!!!要注意我們傳遞過去的只是地址,如下圖所示,我們進行傳遞的時候將ref對象的地址拷貝一份傳遞過去(注意是拷貝一份),當我們沒有對傳遞過去的形參地址進行修改的情況下,對該形參進行修改都會影響原本的實參,例如上面前面的change方法,如果進行對形參的地址進行修改了的話將會和原本的實參斷絕關系,例如上面修改后的change方法。而上面的String的change就不用說了 name= "李四"相當于將name的地址修改為了字符串常量池中的"李四"對象。
ref的存儲結構.png
通過上面的我們明白了什么是引用傳遞和值傳遞。關于String傳參可能大家也有了答案。
String傳參的時候傳遞String對象所指向的地址,但是由于String中沒有方法能夠對value數組進行修改,所以我們在對String參數進行操作的時候都不會改變他的值,很多情況下我們認為String的值變化了都是一種錯覺。比如下面的replace方法
public static void change(String name) {
name.replace('張','李');
}
上面的代碼很容易讓我們產生name中的"張"換成了"李"的錯覺,但是其實并沒有改變,我們可以看一看replace的具體是怎么實現的
replace.png
我們可以看出repalce中并沒有對原本value數組進行更改,而是將value中的數組拷貝到buf中(需要替換的替換),然后返回一個new String。具體其他你認為String內容改變了的地方你可以閱讀源碼進行觀察,你就會發現其實都沒有更改。
關于String的其他內容可以點擊查看
總結
以上是生活随笔為你收集整理的java有string这个类型吗_关于java的String类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql主从复制周期_Mysql主从复
- 下一篇: java random用法_JAVA面试