日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你所认识的String

發(fā)布時(shí)間:2025/5/22 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你所认识的String 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述

String作為非基本數(shù)據(jù)類型,Java開發(fā)中使用頻率最高的一種數(shù)據(jù)類型之一,對于字符號的操作也很頻繁,在使用的同時(shí)我們是否注意到了一下問題?

問題

  • String a = new String("xxx")創(chuàng)建了多少個(gè)對象?
  • String a = "xxx"創(chuàng)建了多少個(gè)對象?
  • 為什么要用StringBuilder來代替"+"?
  • 為什么String作為方法參數(shù),在方法內(nèi)部修改,不會(huì)影響原來的值?
  • 字符串相等的問題?
  • 如何正確的操作字符串?

如上問題我們是否都清晰明了,接下來結(jié)合示例來了解以上問題,同時(shí)讓我們更加清晰的認(rèn)識String

問題一

String a = new String("xxx") 復(fù)制代碼

該語句創(chuàng)建了2個(gè)對象,首先new會(huì)在堆中創(chuàng)建了一個(gè)對象用來存放"xxx",然后變量a指向剛才創(chuàng)建的對象,緊接著會(huì)在常量池中查看是否存在該字符串,如果沒有,創(chuàng)建"xxx"字符串

問題二

String a = "xxx" 復(fù)制代碼

該語句創(chuàng)建了一個(gè)對象,會(huì)在常量池中查看是否存在"xxx"這個(gè)字符串,如果存在,則直接指向,如果不存在,則需要?jiǎng)?chuàng)建"xxx"字符串,然后指向

問題三

源代碼

public class StringAppendTest {public static void main(String[] args) {String str = "abc";for (int i = 0; i < 10000; i++) {str += "def";}} } 復(fù)制代碼

反編譯之后代碼

package com.primary.example.string;public class StringAppendTest {public StringAppendTest(){}public static void main(String args[]){String str = "abc";for(int i = 0; i < 10000; i++)str = (new StringBuilder()).append(str).append("def").toString();} } 復(fù)制代碼

在線反編譯地址:在線反編譯,記得Decompiler類型選擇JAD

如上代碼展示可以看出來,"+"最終會(huì)被反編譯成創(chuàng)建StringBuilder對象,然后調(diào)用append()方法,最終調(diào)用toString

如果是一條語句使用"+"拼接完全沒有問題,如果在循環(huán)中使用的話就會(huì)不斷的創(chuàng)建對象,影響性能。

問題四

示例代碼1

public void test2() {Student student = new Student();student.setId(10001);student.setName("jack");System.out.println("before change,student:" + student);changeStudent(student);System.out.println("after change,student:" + student); }private void changeStudent(Student student) {student.setName("lucky"); } 復(fù)制代碼

打印結(jié)果1

before change,student:Student(id=10001, name=jack) after change,student:Student(id=10001, name=lucky) 復(fù)制代碼

示例代碼2

public void test4() {String str = "jack";System.out.println("before change,str:" + str);changeStr(str);System.out.println("after change,str:" + str); }/*** 通過查看String的源碼,可以看到里面定義的char[]是final,也就是不可變的* 每次對字符串的操作都相當(dāng)于new String()操作* @param str*/ private void changeStr(String str) {str = "smile"; } 復(fù)制代碼

打印結(jié)果1

before change,str:jack after change,str:jack 復(fù)制代碼

如上展示,示例1傳對象在方法內(nèi)部的修改會(huì)影響外部,示例2傳對象在方法內(nèi)部修改卻沒有影響外部,同樣是對象,示例1和示例2卻得到不一樣的效果?

示例1由于傳遞的是地址值,調(diào)用changeStudent()的時(shí)候,形參根據(jù)地址值找到student對象,然后對其修改,由于形參和實(shí)參指向的是同一個(gè)對象,所以方法內(nèi)部的修改會(huì)影響到外部

實(shí)例2傳遞的也是地址值,但是由于String類型是不可變的,每一次賦值都相當(dāng)于重新創(chuàng)建一個(gè)對象,所以內(nèi)部的修改不影響外部

String內(nèi)部字符數(shù)組的定義

private final char value[]; 復(fù)制代碼

問題五

示例1

public void test1() {String str1 = "123";String str2 = "123";System.out.println(str1 == str2); } 復(fù)制代碼

結(jié)果1

true 復(fù)制代碼

示例2

public void test2() {String str1 = "123";String str2 = "12" + "3";System.out.println(str1 == str2); } 復(fù)制代碼

結(jié)果2

true 復(fù)制代碼

示例3

public void test3() {String str1 = "123";String temp = "3";String str2 = "12" + temp;System.out.println(str1 + "=====" + str2);System.out.println(str1 == str2); } 復(fù)制代碼

結(jié)果3

false 復(fù)制代碼

示例4

public void test4() {String str1 = "123";final String temp = "3";String str2 = "12" + temp;System.out.println(str1 == str2); } 復(fù)制代碼

結(jié)果4

true 復(fù)制代碼

示例5

public void test5() {String str1 = "123";final String temp = getTemp();String str2 = "12" + temp;System.out.println(str1 == str2); }public String getTemp() {return "3"; } 復(fù)制代碼

結(jié)果5

false 復(fù)制代碼

結(jié)果是不是很驚訝?為什么值一樣卻不相等?首先"=="比較的是地址,equals()方法比較的是內(nèi)容,但是由于每個(gè)類的equals()方法不一樣,所以需要看具體的實(shí)現(xiàn)

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; } 復(fù)制代碼

可以看到String的equals()方法首先比較地址是否一樣,如果不一樣再比較內(nèi)容是否一樣

然后再回到上面"=="比較的問題,我們首先要明白一個(gè)觀點(diǎn)就是,Java中的常量是在編譯期間已經(jīng)確定好的,無法確定的就會(huì)在堆中

示例1在編譯期間可以確定

示例2在編譯期間也可以確定

示例3在編譯期間無法確定,由于存在變量,變量只有在運(yùn)行的時(shí)候才能確定

示例4在編譯期間可以確定,雖然有變量,但是聲明為常量,常量一旦定義就無法修改,所以編譯時(shí)是可以確定的

示例5在編譯期間無法確定,由于調(diào)用了方法,在運(yùn)行的時(shí)候才能知道方法的返回值

問題六

來看看我們對字符串的操作

str.length(); str.substring() str.indexOf() if (null != str && str != "") {} 復(fù)制代碼

替代方案

StringUtils.length("xxx"); StringUtils.substring("xxx", 0, 5); StringUtils.indexOf("xxx", 1); if (StringUtils.isBlank("xxx")) {} 復(fù)制代碼

我們完全可以使用Apache的工具類來操作,首先是方便,其次是可以避免NullPointerException異常,進(jìn)入工具類的方法實(shí)現(xiàn),可以看到,首先會(huì)對我們傳入的字符串進(jìn)行null判斷,從而避免異常

以上都是個(gè)人理解,如有錯(cuò)誤,歡迎指定,讓我提早走向光明

轉(zhuǎn)載于:https://juejin.im/post/5c94addcf265da60df410a20

總結(jié)

以上是生活随笔為你收集整理的你所认识的String的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。