java中String相等問題

?

判斷兩個字符串是否相等的問題。在編程中,通常比較兩個字符串是否相同的表達式是“==”,但在java中不能這么寫。在java中,用的是equals();

例:A字符串和B和字符串比較:

if(A.equals(B)){

}

返回true?或false.

String?的equals?方法用于比較兩個字符串是否相等。由于字符串是對象類型,所以不能用簡單的“==”判斷。而使用equals比較兩個對象的內容是否相等。

注意:

equals()比較的是對象的內容(區分字母的大小寫格式),但是如果使用“==”比較兩個對象時,比較的是兩個對象的內存地址,所以不相等。即使它們內容相等,但是不同對象的內存地址也是不相同的。

?

(轉載)Java?中String?的相等比較


轉載

轉載 地址:http://wenku.baidu.com/view/d223a71714791711cc791737.html

1.首先介紹三個String對象比較的方法:
(1)equals:比較兩個String對象的值是否相等。例如:
String str1 = "hello quanjizhu";
String str2 =str1+"haha";
String str3 = new String("hello quanjizhu");

System.out.println(str1.equals(str2)); //false
System.out.println(str1.equals(str3)); //true

(2)= =:比較兩個String對象的指向的內存地址是否相等。例如:
String str1 = "hello quanjizhu";
String str2 =str1+"haha";
String str3 = new String("hello quanjizhu");

System.out.println(str1==str2);??
System.out.println(str1==str3);?
輸出結果都為false。

3.原理
要理解 java中String的運作方式,必須明確一點:String是一個非可變類(immutable)。什么是非可變類呢?簡單說來,非可變類的實例是不能被修改的,每個實例中包含的信息都必須在該實例創建的時候就提供出來,并且在對象的整個生存周期內固定不變。java為什么要把String設計為非可變類呢?你可以問問 james Gosling :)。但是非可變類確實有著自身的優勢,如狀態單一,對象簡單,便于維護。其次,該類對象對象本質上是線程安全的,不要求同步。此外用戶可以共享非可變對象,甚至可以共享它們的內部信息。(詳見 《Effective java》item 13)。String類在java中被大量運用,甚至在class文件中都有其身影,因此將其設計為簡單輕便的非可變類是比較合適的。
(1)創建。
????好了,知道String是非可變類以后,我們可以進一步了解String的構造方式了。創建一個Stirng對象,主要就有以下兩種方式:


java 代碼
String str1 = new String("abc");???
Stirng str2 = "abc";?
?????雖然兩個語句都是返回一個String對象的引用,但是jvm對兩者的處理方式是不一樣的。對于第一種,jvm會馬上在heap中創建一個String對象,然后將該對象的引用返回給用戶。對于第二種,jvm首先會在內部維護的strings pool中通過String的 equels 方法查找是對象池中是否存放有該String對象,如果有,則返回已有的String對象給用戶,而不會在heap中重新創建一個新的String對象;如果對象池中沒有該String對象,jvm則在heap中創建新的String對象,將其引用返回給用戶,同時將該引用添加至strings pool中。注意:使用第一種方法創建對象時,jvm是不會主動把該對象放到strings pool里面的,除非程序調用 String的intern方法。看下面的例子:

java 代碼
String str1 = new String("abc"); //jvm 在堆上創建一個String對象??
?
?//jvm 在strings pool中找不到值為“abc”的字符串,因此??
?//在堆上創建一個String對象,并將該對象的引用加入至strings pool中??
?//此時堆上有兩個String對象??
Stirng str2 = "abc";??
?
?if(str1 == str2){??
?????????System.out.println("str1 == str2");??
?}else{??
?????????System.out.println("str1 != str2");??

??//打印結果是 str1 != str2,因為它們是堆上兩個不同的對象??
?
??String str3 = "abc";??
?//此時,jvm發現strings pool中已有“abc”對象了,因為“abc”equels “abc”??
?//因此直接返回str2指向的對象給str3,也就是說str2和str3是指向同一個對象的引用??
??if(str2 == str3){??
?????????System.out.println("str2 == str3");??
??}else{??
?????????System.out.println("str2 != str3");??
??}??
?//打印結果為 str2 == str3?
???再看下面的例子:


java 代碼
String str1 = new String("abc"); //jvm 在堆上創建一個String對象??
?
str1 = str1.intern();??
//程序顯式將str1放到strings pool中,intern運行過程是這樣的:首先查看strings pool??
//有沒“abc”對象的引用,沒有,則在堆中新建一個對象,然后將新對象的引用加入至??
//strings pool中。執行完該語句后,str1原來指向的String對象已經成為垃圾對象了,隨時會??
//被GC收集。??
?
//此時,jvm發現strings pool中已有“abc”對象了,因為“abc”equels “abc”??
//因此直接返回str1指向的對象給str2,也就是說str2和str1引用著同一個對象,??
//此時,堆上的有效對象只有一個。??
Stirng str2 = "abc";??
?
?if(str1 == str2){??
?????????System.out.println("str1 == str2");??
?}else{??
?????????System.out.println("str1 != str2");??
?}??
??//打印結果是 str1 == str2??
?
為什么jvm可以這樣處理String對象呢?就是因為String的非可變性。既然所引用的對象一旦創建就永不更改,那么多個引用共用一個對象時互不影響。


(2)串接(Concatenation)。
?????java程序員應該都知道濫用String的串接操作符是會影響程序的性能的。性能問題從何而來呢?歸根結底就是String類的非可變性。既然String對象都是非可變的,也就是對象一旦創建了就不能夠改變其內在狀態了,但是串接操作明顯是要增長字符串的,也就是要改變String的內部狀態,兩者出現了矛盾。怎么辦呢?要維護String的非可變性,只好在串接完成后新建一個String 對象來表示新產生的字符串了。也就是說,每一次執行串接操作都會導致新對象的產生,如果串接操作執行很頻繁,就會導致大量對象的創建,性能問題也就隨之而來了。
????為了解決這個問題,jdk為String類提供了一個可變的配套類,StringBuffer。使用StringBuffer對象,由于該類是可變的,串接時僅僅時改變了內部數據結構,而不會創建新的對象,因此性能上有很大的提高。針對單線程,jdk 5.0還提供了StringBuilder類,在單線程環境下,由于不用考慮同步問題,使用該類使性能得到進一步的提高。

(3)String的長度
???我們可以使用串接操作符得到一個長度更長的字符串,那么,String對象最多能容納多少字符呢?查看String的源代碼我們可以得知類String中是使用域 count 來記錄對象字符的數量,而count 的類型為 int,因此,我們可以推測最長的長度為 2^32,也就是4G。
????不過,我們在編寫源代碼的時候,如果使用 Sting str = "aaaa";的形式定義一個字符串,那么雙引號里面的ASCII字符最多只能有 65534 個。為什么呢?因為在class文件的規范中, CONSTANT_Utf8_info表中使用一個16位的無符號整數來記錄字符串的長度的,最多能表示 65536個字節,而java class 文件是使用一種變體UTF-8格式來存放字符的,null值使用兩個字節來表示,因此只剩下 65536- 2 = 65534個字節。也正是變體UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么雙引號中字符的數量會更少(一個中文字符占用三個字節)。如果超出這個數量,在編譯的時候編譯器會報錯。


(3)compareTo:比較兩個String對象的值是否相等。例如:
String str1 = "hello quanjizhu";
String str2 =str1+"haha";
String str3 = new String("hello quanjizhu");

System.out.println(str1.compareTo(str2));?
System.out.println(str1.compareTo(str3));?
輸出結果都為0。(若輸出結果大于0表示str1大于str2)
2.String類的幾種初始化方法的區別
(1) String str1 = "hello quanjizhu";
首先到String pool中查找有沒有值為hello quanjizhu的對象,若有則讓str1直接指向此內存地址;若沒有則在內存堆中重新開辟空間給str1,并把hello quanjizhu加到String pool中。
(2)String str3 = new String("hello quanjizhu");
每次初始化都會重新在內存堆中開辟空間給新的對象,而不會到String pool中查找,更不會添加到String pool中。除非顯示的調用intern方法。
str3.interl();這時就會把hello quanjizhu加到String pool中。
(3)
String str1 = "hello quanjizhu";
String str2 ="hello" +"quanjizhu";
?String str3 ="hello "+"quanjizhu";在編譯的時候會優化成String str3 = "hello quanjizhu";所有str1和str2指向的是同一內存地址。
(4)
String var = “quanjizhu“;
String str4 = “hello “+var;
??System.out.println(str1= =str4)的結果是什么呢?輸出結果是false,證明了String str4 = “hello “+var;
在內存堆中會重新分配空間,而不是讓str4指向var的地址。換用一種定義方法:str4 = (“hello “+var4).intern();intern()方法告訴編譯器將此結果放到String pool里,因此,System.out.println(str1= =str4)輸出結構將是true;

轉載于:https://www.cnblogs.com/guoziyi/p/5993085.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457091.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457091.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457091.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux proc文件 write的原子性,linux - Linux中writev()系統調用的原子性 - 堆棧內存溢出...

在fs.h找到它:static inline void file_start_write(struct file *file){if (!S_ISREG(file_inode(file)->i_mode))return;__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);}然后在super.c:/** This is an internal function, p…

關于對發送HTTP請求以及解析服務器返回的數據操作的提取到一個公共類中進行封裝

創建一個名為HttpUtil的類并提供名為sendHttpRequest靜態方法.相關代碼如下: package com.hzy.networktest;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;p…

初始化CSS

不同的瀏覽器默認樣式不一樣,所以容易出現兼容性問題,每次寫網頁時都應該都網頁的css或HTML標簽進行初始化 這樣可以節約代碼,節約網頁下載時間,是網頁內容更加簡潔, 大致需要初始化的地方有 H1-H4標簽,table標簽,文字大小,文字沒有鏈接,超鏈接樣式,DIV,居中,ol,ul,li,img等等的…

Day10-時間

UTC(世界協調時間):格林尼織天文時間 在中國來說是UTC8 DST(夏令時):是一種節約能源而人為規定時間制度,在夏季調快一個小時時間的表示形式: 1、時間戳 以整形或浮點型表示時間的一個以秒為單位的時間間隔 …

WebForm 分頁與組合查詢

1.封裝實體類 2.寫查詢方法 //SubjectData類 public List<Subject> Select(string name){List<Subject> list new List<Subject>();cmd.CommandText "select *from Subject where SubjectName like a ";cmd.Parameters.Clear();cmd.Parameters.A…

linux如何輸出當前時間,如何在linux下輸出當前時間

用localtime可直接分解出年月日時分秒QUOTE:struct tm *ptm;long ts;int y,m,d,h,n,s;ts time(NULL);ptm localtime(&ts);y ptm->tm_year1900; //年m ptm->tm_mon1; //月d ptm->tm_mday; //日h ptm->tm_hour; //時n ptm->tm_min; //分s ptm->tm_…

node.js簡單爬蟲

這里假設你已經安裝好node.js和npm&#xff0c;如果沒有安裝&#xff0c;請參閱其他教程安裝。 配置首先是來配置package.json文件&#xff0c;這里使用express,request和cheerio。package.json如下&#xff1a; {"name": "node-scrape","version&quo…

Day11-遞歸性能測試

import time time.clock() sum 0 for i in range (1000000000):sumi print(time.clock()) 慎用 慎用 慎用

關于在新建的package中用SetContentView()函數時無法找到已創建的R.layout的布局文件的的問題的解決辦法

問題描述如下&#xff1a; 解決途徑&#xff1a;是在導入包的過程中&#xff0c;錯誤的將系統自動將Android.R這個包導入最終導致用setContenView()加載布局時只能顯示系統自帶的布局&#xff0c;無法顯示自己已經創建的布局。只需將相應活動中導入的Android.R包刪除&#xff0…

Struts2入門(二)——配置攔截器

一、前言 之前便了解過&#xff0c;Struts 2的核心控制器是一個Filter過濾器&#xff0c;負責攔截所有的用戶請求&#xff0c;當用戶請求發送過來時&#xff0c;會去檢測struts.xml是否存在這個action&#xff0c;如果存在&#xff0c;服務器便會自動幫我們跳轉到指定的處理類中…

linux固態機械分區嗎,不再疑惑!實測數據后才知道固態硬盤究竟要不要分區

不再疑惑&#xff01;實測數據后才知道固態硬盤究竟要不要分區2019-12-10 20:52:00162點贊594收藏177評論前幾年的固態硬盤價格昂貴&#xff0c;一般用戶會選擇128G或256G的固態作為系統盤&#xff0c;由于單盤空間不大&#xff0c;一般都會配合機械硬盤使用&#xff0c;無需考…

關于無法加載已創建的布局文件的問題的解決方案以及已布局在對應的R文件中未生成相應ID的問題的解決

先來說下創建后的Layout布局文件在對應的R文件中不能生成相應的ID問題&#xff0c;一般情況下之所以出現這種問題是應為自己的res文件中有錯誤的文件&#xff1a;對應的是錯誤的文件格式名稱&#xff0c;以及錯誤的文件內容等。博主就遇到過為drawable文件起了一個非法的名稱&a…

安卓手機的后門控制工具SPADE

SPADE&#xff0c;一款安卓手機的后門控制工具&#xff0c;安全研究人員可以以此了解和研究安卓后門原理。 首先&#xff0c;我們從網站www.apk4fun.com下載apk文件&#xff0c;如ccleaner。然后&#xff0c;我們安裝spade git clone https://github.com/suraj-root/spade.git …

Day12-date time

import datetimedatetime比time高級了不少&#xff0c;可以理解為datetime基于time進行了封裝&#xff0c;提供了&#xff0c; 更為實用的函數&#xff0c;并且datetime模塊的接口更直觀更容易調用模塊中的類&#xff1a; datetime 同時又時間和日期 imedelta 主…

MySQL案例-open too many files,MyISAM與partition

-------------------------------------------------------------------------------------------------短文---------------------------------------------------------------------------------------------------------------長話短說~現象: error log中批量刷錯誤日志, 形…

關于異常:HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection的解決辦法

<span style"font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style"font-size:18px;">今天在寫一個app時&#xff0c;當實現從網絡上獲取圖片資源&#xff0c;發送HTTPURLConnection的時候拋出這樣…

linux網卡有很多error,教你設置win7系統虛擬機安裝linux提示network error的解決方法...

很多朋友在使用電腦的過程中&#xff0c;會發現win7系統虛擬機安裝linux提示network error的現象&#xff0c;當遇到win7系統虛擬機安裝linux提示network error的問題&#xff0c;我們要怎么解決呢&#xff1f;如今還有很多用戶不知道如何處理win7系統虛擬機安裝linux提示netwo…

codevs2171 棋盤覆蓋

題目描述 Description給出一張n*n(n<100)的國際象棋棋盤&#xff0c;其中被刪除了一些點&#xff0c;問可以使用多少1*2的多米諾骨牌進行掩蓋。 輸入描述 Input Description第一行為n&#xff0c;m&#xff08;表示有m個刪除的格子&#xff09;第二行到m1行為x,y&#xff0c…

Day13-日歷模塊

import calendar日歷模塊 #使用#返回制定歿年某月日歷 print(calendar.month(2019,3)) #返回指定年份的日歷 print(calendar.calendar(2019)) #判斷閏年返回True 或者Flase print(calendar.isleap(2000)) #返回某個月的weekd的第一天和這個月所有的天數 print(calendar.monthra…