java有string这个类型吗_关于java的String类型
String類型的不可變
眾所周知,String類型是不可變的,一旦String對象被創(chuàng)建好了則這個字符串中的序列就不可改變。
為什么String類型是不可變?
根據(jù)閱讀源碼可知,String類是一個final類,但是String不可變并不是因?yàn)樗且粋€final類,final修飾的類只是不能被繼承,因?yàn)橛凶址A砍剡@個東西,如果String類能被繼承就會出現(xiàn)安全問題。關(guān)于String不可變的原因是因?yàn)橄旅孢@句代碼:
private final char value[];
value負(fù)責(zé)存儲String的值,因?yàn)関alue是用final修飾的,所以value的地址不能被改變(但是數(shù)組的值可以被改變),又因?yàn)樵赟tring類中并沒有任何方法能夠修改value的元素,所以String是不可變的。但是在有的時候我們認(rèn)為字符串改變了啊,例如String s="hi"; s+=" world";s輸出就會變成"hi world",這是因?yàn)橹匦陆o了s一個字符串對象,相加后的對象和以前的對象不一樣,后面將會有代碼演示。
String類型真的不可變嗎?
因?yàn)関alue是一個char數(shù)組,他只是地址不可變,其中的值是可變的,String不可變是因?yàn)樗鼪]有提供給我們可以修改value的方法,但是我們可以通過反射獲取到value數(shù)組,然后修改它的值,這樣可以實(shí)現(xiàn)“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);
輸出結(jié)果
true
hello world
hello world
true
hiiii world
hiiii world
通過上面可以看出當(dāng)我們改變s1的值時s2被改變了。
關(guān)于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);
輸出結(jié)果
true
true
false
false
false
false
false
false
hello world!
hello world
false
在String中使用new就新創(chuàng)建一個對象,不論字符串常量池是否有它,而s3和s10的區(qū)別在于,在編譯階段就能確定s3,因?yàn)閟3指定了是"hello "和"world"相結(jié)合,而s10在編譯階段程序并不能確定s8和s7的值。
String一些方法可能產(chǎn)生新的對象
subString
當(dāng)subString截取的字符串就是本身的時候,返回本身,否則返回一個新聲明的字符串。
replace
如果新字符和要替換的一樣的話,返回本身,否則返回一個新聲明的字符串。
toCharArray
返回一個新的字符數(shù)組,對改數(shù)組進(jìn)行修改不會對String產(chǎn)生任何影響。
toString
返回的是字符串本身
trim
trim方法是返回String對象的一個副本,該副本去除了原來字符串中的首部和尾部空白。但如果String對象首部和尾部沒有空白的話,則返回自身。否則調(diào)用subString方法返回一個嶄新的String對象(真子串,subString方法中說過)。
關(guān)于String傳參
在開始String傳參的時候先看看參數(shù)傳遞的兩大類型:
值傳遞:在我們進(jìn)行參數(shù)傳遞的時候?qū)?shí)參拷貝一份傳遞過去,所以在方法里面對其更改不會對原本的造成影響。
引用傳遞:在java中引用傳遞是拷貝該對象的地址傳遞過去,如果在傳遞過去的地址對應(yīng)的對象上進(jìn)行修改就會影響原本的值。
具體例子如下:
//自己聲明的一個類
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函數(shù)改變?nèi)缦?/p>
public static void change(Ref ref) {
Ref ref1 = new Ref();
ref = ref1;
ref.setName("李四");
}
/*運(yùn)行
Ref{name='張三'}
5
張三
*/
通過上面的例子我們發(fā)現(xiàn)對象的傳遞如果在方法里面進(jìn)行了修改將會改變原本的值。但是!!!要注意我們傳遞過去的只是地址,如下圖所示,我們進(jìn)行傳遞的時候?qū)ef對象的地址拷貝一份傳遞過去(注意是拷貝一份),當(dāng)我們沒有對傳遞過去的形參地址進(jìn)行修改的情況下,對該形參進(jìn)行修改都會影響原本的實(shí)參,例如上面前面的change方法,如果進(jìn)行對形參的地址進(jìn)行修改了的話將會和原本的實(shí)參斷絕關(guān)系,例如上面修改后的change方法。而上面的String的change就不用說了 name= "李四"相當(dāng)于將name的地址修改為了字符串常量池中的"李四"對象。
ref的存儲結(jié)構(gòu).png
通過上面的我們明白了什么是引用傳遞和值傳遞。關(guān)于String傳參可能大家也有了答案。
String傳參的時候傳遞String對象所指向的地址,但是由于String中沒有方法能夠?qū)alue數(shù)組進(jìn)行修改,所以我們在對String參數(shù)進(jìn)行操作的時候都不會改變他的值,很多情況下我們認(rèn)為String的值變化了都是一種錯覺。比如下面的replace方法
public static void change(String name) {
name.replace('張','李');
}
上面的代碼很容易讓我們產(chǎn)生name中的"張"換成了"李"的錯覺,但是其實(shí)并沒有改變,我們可以看一看replace的具體是怎么實(shí)現(xiàn)的
replace.png
我們可以看出repalce中并沒有對原本value數(shù)組進(jìn)行更改,而是將value中的數(shù)組拷貝到buf中(需要替換的替換),然后返回一個new String。具體其他你認(rèn)為String內(nèi)容改變了的地方你可以閱讀源碼進(jìn)行觀察,你就會發(fā)現(xiàn)其實(shí)都沒有更改。
關(guān)于String的其他內(nèi)容可以點(diǎn)擊查看
總結(jié)
以上是生活随笔為你收集整理的java有string这个类型吗_关于java的String类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql主从复制周期_Mysql主从复
- 下一篇: java random用法_JAVA面试