国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

JAVA中的字符串池和字符對象

2019-11-17 03:56:55
字體:
來源:轉載
供稿:網友
java的都知道String這個類,是我們一般都要用的一個類,那么我們對這個類又了解多少呢?下面我來給大家介紹下這個類! String 這個類有兩大模式一個是對象池的概念,而另一個就是不變模式! String類和對象池 我們知道得到String對象有兩種辦法: String str1="hello"; String str2=new String("hello"); 這兩種創建String對象的方法有什么差異嗎?當然有差異,差異就在于第一種方法在對象池中拿對象,第二種方法直接生成新的對象。在JDK5.0里面,Java虛擬機在啟動的時候會實例化9個對象池,這9個對象池分別用來存儲8種基本類型的包裝類對象和String對象。當我們在程序中直接用雙引號括起來一個字符串時,JVM就到String的對象池里面去找看是否有一個值相同的對象,如果有,就拿現成的對象,如果沒有就在對象池里面創建一個對象,并返回。所以我們發現下面的代碼輸出true: String str1="hello"; String str2="hello"; System.out.PRintln(str1==str2); 這說明str1和str2指向同一個對象,因為它們都是在對象池中拿到的,而下面的代碼輸出為false: String str3="hello" String str4=new String("hello"); System.out.println(str3==str4); 因為在任何情況下,只要你去new一個String對象那都是創建了新的對象。與此類似的,在JDK5.0里面8種基本類型的包裝類也有這樣的差異: Integer i1=5;//在對象池中拿 Integer i2 =5;//所以i1==i2 Integer i3=new Integer(5);//重新創建新對象,所以i2!=i3 對象池的存在是為了避免頻繁的創建和銷毀對象而影響系統性能,那我們自己寫的類是否也可以使用對象池呢?當然可以,考察以下代碼: import java.util.*; public class Student { private String name; private int age; private static HashSet pool = new HashSet(); // 對象池 public Student(String name, int age) { this.name = name; this.age = age; } // 使用對象池來得到對象的方法 public static Student newInstance(String name, int age) { // 循環遍歷對象池 for (Student stu : pool) { if (stu.name.equals(name) && stu.age == age) { return stu; } } // 如果找不到值相同的Student對象,則創建一個Student對象 //并把它加到對象池中然后返回該對象。 Student stu = new Student(name, age); pool.add(stu); return stu; } } class Test { public static void main(String[] args) { Student stu1 = Student.newInstance("tangliang", 30); // 對象池中拿 Student stu2 = Student.newInstance("tangliang", 30); // 所以stu1==stu2 Student stu3 = new Student("tangliang", 30); // 重新創建,所以stu1!=stu3 System.out.println(stu1 == stu2); System.out.println(stu1 == stu3); } } 6,2.0-1.1==0.9嗎? 考察下面的代碼: double a=2.0,b=1.1,c=0.9; if(a-b==c){ System.out.println("YES!"); }else{ System.out.println("NO!"); } 以上代碼輸出的結果是多少呢?你認為是“YES!”嗎?那么,很遺憾的告訴你,不對,Java語言再一次cheat了你,以上代碼會輸出“NO!”。為什么會這樣呢?其實這是由實型數據的存儲方式決定的。我們知道實型數據在內存空間中是近似存儲的,所以2.0-1.1的結果不是0.9,而是0.88888888889。所以在做實型數據是否相等的判斷時要非常的謹慎。一般來說,我們不建議在代碼中直接判斷兩個實型數據是否相等,如果一定要比較是否相等的話我們也采用以下方式來判斷: if(Math.abs(a-b)<1e-5){ //相等 }else{ //不相等 } 上面的代碼判斷a與b之差的絕對值是否小于一個足夠小的數字,如果是,則認為a與b相等,否則,不相等。 7,判斷奇數 以下的方法判斷某個整數是否是奇數,考察是否正確: public boolean isOdd(int n){ return (n%2==1); } 很多人認為上面的代碼沒問題,但實際上這段代碼隱藏著一個非常大的BUG,當n的值是正整數時,以上的代碼能夠得到正確結果,但當n的值是負整數時,以上方法不能做出正確判斷。例如,當n=-3時,以上方法返回false。因為根據Java語言規范的定義,Java語言里的求余運算符(%)得到的結果與運算符左邊的值符號相同,所以,-3%2的結果是-1,而不是1。那么上面的方法正確的寫法應該是: public boolean isOdd(int n){ return (n%2!=0); } 8,拓寬數值類型會造成精度丟失嗎? Java語言的8種基本數據類型中7種都可以看作是數值類型,我們知道對于數值類型的轉換有一個規律:從窄范圍轉化成寬范圍能夠自動類型轉換,反之則必須強制轉換。請看下圖: byte-->short-->int-->long-->float-->double char-->int 我們把順箭頭方向的轉化叫做拓寬類型,逆箭頭方向的轉化叫做窄化類型。一般我們認為因為順箭頭方向的轉化不會有數據和精度的丟失,所以Java語言允許自動轉化,而逆箭頭方向的轉化可能會造成數據和精度的丟失,所以Java語言要求程序員在程序中明確這種轉化,也就是強制轉換。那么拓寬類型就一定不會造成數據和精度丟失嗎?請看下面代碼: int i=2000000000; int num=0; for(float f=i;f< 哈哈,你快要不相信你的眼睛了,結果竟然是true;難道f1和f2是相等的嗎?是的,就是這樣,這也就能解釋為什么上一段代碼輸出的結果是0,而不是50了。那為什么會這樣呢?關鍵原因在于你將int值自動提升為float時發生了數據精度的丟失,i的初始值是2000000000,這個值非常接近Integer.MAX_VALUE,因此需要用31位來精確表示,而float只能提供24位數據的精度(另外8位是存儲位權,見IEEE745浮點數存儲規則)。所以在這種自動轉化的過程中,系統會將31位數據的前24位保留下來,而舍棄掉最右邊的7位,所以不管是2000000000還是2000000050,舍棄掉最右邊7位后得到的值是一樣的。這就是為什么f1="=f2的原因了。" System.out.println(f1="=f2);" f2="i+50;" float f1="i;" i="2000000000;" int ,那么請運行一下,結果會讓你大吃一驚!沒錯,輸出結果是0,難道這個循環根本就沒有執行哪怕一次?確實如此,如果你還不死心,我帶你你看一個更詫異的現象,運行以下代碼,看輸出什么? 如果你回答50 請考察以上代碼輸出多少? System.out.println(num); } num++;> 9,i=i+1和i+=1完全等價嗎? 可能有很多程序員認為i+=1只是i=i+1的簡寫方式,其實不然,它們一個使用簡單賦值運算,一個使用復合賦值運算,而簡單賦值運算和復合賦值運算的最大差別就在于:復合賦值運算符會自動地將運算結果轉型為其左操作數的類型。看看以下的兩種寫法,你就知道它們的差別在哪兒了: (1) byte i=5; i+=1; (2) byte i=5; i=i+1; 第一種寫法編譯沒問題,而第二種寫法卻編譯通不過。原因就在于,當使用復合賦值運算符進行操作時,即使右邊算出的結果是int類型,系統也會將其值轉化為左邊的byte類型,而使用簡單賦值運算時沒有這樣的優待,系統會認為將i+1的值賦給i是將int類型賦給byte,所以要求強制轉換。理解了這一點后,我們再來看一個例子: byte b=120; b+=20; System.out.println("b="+b); 說到這里你應該明白了,上例中輸出b的值不是140,而是-116。因為120+20的值已經超出了一個byte表示的范圍,而當我們使用復合賦值運算時系統會自動作類型的轉化,將140強轉成byte,所以得到是-116。由此可見,在使用復合賦值運算符時還得小心,因為這種類型轉換是在不知不覺中進行的,所以得到的結果就有可能和你的預想不一樣。 對于J2ME的答案也是1一個 在J2ME里面沒有對象池的概念。 在JDK中有jdk里面有9個對象池,8個基本類包裝類對象和String類對象。 不變模式 什么是不變模式呢? String s = "xx"; String s = "aa"; 不變模式就是 一個字符串對象 創建后它的值就不能再被改變。每改變一次就產生一個垃圾,它只是一個對象的引用地址,指向一個值,如果把他的值換了,那么只是換了一個對象的引用地址,至始至終沒有改變它本身的值,如果要在系統中頻繁的使用字符串引用,那么建議使用StringBuffer,先放到緩沖區里,然后直接全部寫入。

發表于 @ 2009年12月


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/wuzhelan/archive/2009/12/17/5027549.aspx
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南部县| 百色市| 治多县| 沁水县| 万州区| 七台河市| 保山市| 邮箱| 大化| 剑河县| 富平县| 浮梁县| 黔东| 噶尔县| 上杭县| 芒康县| 长治市| 云霄县| 马山县| 洪雅县| 板桥市| 清流县| 陆丰市| 青阳县| 浮山县| 平遥县| 永福县| 克东县| 东丰县| 新丰县| 乌审旗| 田林县| 丹凤县| 花莲县| 宁化县| 宁津县| 江口县| 娄底市| 吉林市| 晴隆县| 满城县|