<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 1  文章 - 3  trackbacks - 0
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567


    常用鏈接

    留言簿(1)

    隨筆檔案

    文章分類

    文章檔案

    相冊(cè)

    搜索

    •  

    最新評(píng)論

    • 1.?re: EXT亂碼
    • @lyq
      我們用的是UTF-8
    • --gkc
    • 2.?re: EXT亂碼
    • 你們工程里面用的編碼格式是utf-8嗎?如果不是的話,怎么只要把method=“post”就行了呢?

      那如果編碼格式是 gbk/gb2312,中文亂碼的問題怎么處理的呢?
    • --lyq
    • 3.?re: EXT出錯(cuò):undefined
    • 謝了,哥們.我也折騰了N久,最后被你的帖啟發(fā)了!
    • --小波
    String類在java中被大量運(yùn)用,甚至在class文件中都有其身影,因此將其設(shè)計(jì)為簡(jiǎn)單輕便的非可變類是比較合適的。

     

    一、創(chuàng)建。
    好了,知道String是非可變類以后,我們可以進(jìn)一步了解String的構(gòu)造方式了。創(chuàng)建一個(gè)Stirng對(duì)象,主要就有以下兩種方式:
    java 代碼

    1. String str1 = new String("abc");
    2. Stirng str2 = "abc";

     

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

    1. String str1 = new String("abc"); //jvm 在堆上創(chuàng)建一個(gè)String對(duì)象
    2.
    3. //jvm 在strings pool中找不到值為“abc”的字符串,因此
    4. //在堆上創(chuàng)建一個(gè)String對(duì)象,并將該對(duì)象的引用加入至strings pool中
    5. //此時(shí)堆上有兩個(gè)String對(duì)象
    6. Stirng str2 = "abc";
    7.
    8. if(str1 == str2){
    9. System.out.println("str1 == str2");
    10. }else{
    11. System.out.println("str1 != str2");
    12. }
    13. //打印結(jié)果是 str1 != str2,因?yàn)樗鼈兪嵌焉蟽蓚€(gè)不同的對(duì)象
    14.
    15. String str3 = "abc";
    16. //此時(shí),jvm發(fā)現(xiàn)strings pool中已有“abc”對(duì)象了,因?yàn)?#8220;abc”equels “abc”
    17. //因此直接返回str2指向的對(duì)象給str3,也就是說str2和str3是指向同一個(gè)對(duì)象的引用
    18. if(str2 == str3){
    19. System.out.println("str2 == str3");
    20. }else{
    21. System.out.println("str2 != str3");
    22. }
    23. //打印結(jié)果為 str2 == str3

    再看下面的例子:
    java 代碼

    1. String str1 = new String("abc"); //jvm 在堆上創(chuàng)建一個(gè)String對(duì)象
    2.
    3. str1 = str1.intern();
    4. //程序顯式將str1放到strings pool中,intern運(yùn)行過程是這樣的:首先查看strings pool
    5. //有沒“abc”對(duì)象的引用,沒有,則在堆中新建一個(gè)對(duì)象,然后將新對(duì)象的引用加入至
    6. //strings pool中。執(zhí)行完該語句后,str1原來指向的String對(duì)象已經(jīng)成為垃圾對(duì)象了,隨時(shí)會(huì)
    7. //被GC收集。
    8.
    9. //此時(shí),jvm發(fā)現(xiàn)strings pool中已有“abc”對(duì)象了,因?yàn)?#8220;abc”equels “abc”
    10. //因此直接返回str1指向的對(duì)象給str2,也就是說str2和str1引用著同一個(gè)對(duì)象,
    11. //此時(shí),堆上的有效對(duì)象只有一個(gè)。
    12. Stirng str2 = "abc";
    13.
    14. if(str1 == str2){
    15. System.out.println("str1 == str2");
    16. }else{
    17. System.out.println("str1 != str2");
    18. }
    19. //打印結(jié)果是 str1 == str2
    20.

    為什么jvm可以這樣處理String對(duì)象呢?就是因?yàn)镾tring的非可變性。既然所引用的對(duì)象一旦創(chuàng)建就永不更改,那么多個(gè)引用共用一個(gè)對(duì)象時(shí)互不影響。


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

    三、String的長(zhǎng)度
    我們可以使用串接操作符得到一個(gè)長(zhǎng)度更長(zhǎng)的字符串,那么,String對(duì)象最多能容納多少字符呢?查看String的源代碼我們可以得知類String中是使用域 count 來記錄對(duì)象字符的數(shù)量,而count 的類型為 int,因此,我們可以推測(cè)最長(zhǎng)的長(zhǎng)度為 2^32,也就是4G。
    不過,我們?cè)诰帉懺创a的時(shí)候,如果使用 Sting str = "aaaa";的形式定義一個(gè)字符串,那么雙引號(hào)里面的ASCII字符最多只能有 65534 個(gè)。為什么呢?因?yàn)樵赾lass文件的規(guī)范中, CONSTANT_Utf8_info表中使用一個(gè)16位的無符號(hào)整數(shù)來記錄字符串的長(zhǎng)度的,最多能表示 65536個(gè)字節(jié),而java class 文件是使用一種變體UTF-8格式來存放字符的,null值使用兩個(gè)字節(jié)來表示,因此只剩下 65536- 2 = 65534個(gè)字節(jié)。也正是變體UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么雙引號(hào)中字符的數(shù)量會(huì)更少(一個(gè)中文字符占用三個(gè)字節(jié))。如果超出這個(gè)數(shù)量,在編譯的時(shí)候編譯器會(huì)報(bào)錯(cuò)。

    對(duì)String類的理解網(wǎng)上有很多的資料,個(gè)人覺得很多都是錯(cuò)誤的,錯(cuò)誤的解釋危害性更大。所以為了解釋清楚,就來看代碼,代碼運(yùn)行出的結(jié)果才是最具有說服力的。說明:以下都是個(gè)人的理解,歡迎指正。
    Java代碼 復(fù)制代碼

    1. public class StringTest {
    2. public static void main(String[] args) {
    3. String str1 = new String("abc");
    4.
    5. String str2 = "abc";
    6.
    7. if (str1 == str2) {
    8. System.out.println("str1 == str2");
    9. } else {
    10. System.out.println("str1 != str2");
    11. }
    12.
    13. String str3 = "abc";
    14. if (str2 == str3) {
    15. System.out.println("str2 == str3");
    16. } else {
    17. System.out.println("str2 != str3");
    18. }
    19.
    20. str1 = str1.intern();
    21.
    22. if (str1 == str2) {
    23. System.out.println("str1 == str2");
    24. } else {
    25. System.out.println("str1 != str2");
    26. }
    27.
    28. String str4 = new String("abc");
    29. str4 = str4.intern();
    30.
    31. if (str1 == str4) {
    32. System.out.println("str1 == str4");
    33. } else {
    34. System.out.println("str1 != str4");
    35. }
    36. }
    37.
    38. }


    運(yùn)行結(jié)果:

    str1 != str2
    str2 == str3
    str1 == str2
    str1 == str4


    看看運(yùn)行結(jié)果后,給出我自己的理解說明:

    1、String有一個(gè)所謂的String pool,這是一個(gè)什么東西呢,我理解是它是堆(heap)上特殊的一個(gè)空間(我叫它特殊堆)。注意它也是在堆上。

    2、產(chǎn)生String類型的對(duì)象有兩種方法,那么這兩種方法有什么區(qū)別呢?我的理解是String str = “abc”是先用equals方法(String類覆蓋了equals方法)判斷這個(gè)特殊堆(String pool)是否有abc,有則將原來在棧中指向abc的引用賦值給str,否則就在這個(gè)特殊堆(String pool)上創(chuàng)建一個(gè)abc對(duì)象。String str2 = new String("abc")則是在普通堆上創(chuàng)建abc對(duì)象。所以str和str2是指向不同的對(duì)象,它們是不同的。

    3、String有個(gè)intern()方法,這個(gè)方法是個(gè)本地方法,當(dāng)用String str2 = new String("abc")來創(chuàng)建對(duì)象時(shí),它相當(dāng)于告訴JVM,我這個(gè)abc對(duì)象是放在特殊堆(String pool)上的。所以第三個(gè)打印結(jié)果是相等的。

    4、需要注意的一點(diǎn):String是final類,它是恒定類,一旦創(chuàng)建就無法改變,所以用intern()方法是重新在String pool中創(chuàng)建了一個(gè)新的對(duì)象。

    5、String類有一個(gè)伴隨類StringBuffer,需要了解它們之間的區(qū)別請(qǐng)google之。

    posted on 2009-10-13 11:56 ...... 閱讀(108) 評(píng)論(0)  編輯  收藏 所屬分類: JAVA

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产精品国产免费无码专区不卡| 丁香花免费高清视频完整版| 国产免费怕怕免费视频观看| 亚洲一日韩欧美中文字幕在线| 免费观看美女用震蛋喷水的视频 | 亚洲精品夜夜夜妓女网| 污视频网站免费在线观看| 亚洲AV永久无码精品一区二区国产| 精品无码专区亚洲| 亚洲AV无码不卡在线观看下载| 黄色a三级免费看| 亚洲免费人成在线视频观看| 免费无码作爱视频| 老司机亚洲精品影院无码| 精品免费人成视频app| 日韩亚洲产在线观看| 国产精品色午夜免费视频| 人人爽人人爽人人片av免费 | 亚洲免费视频网站| 青娱乐免费视频在线观看| 亚洲成av人无码亚洲成av人| 亚洲不卡无码av中文字幕| 大地资源中文在线观看免费版| 亚洲丝袜美腿视频| 最近最新中文字幕完整版免费高清 | 免费国产真实迷j在线观看| aaa毛片免费观看| 亚洲第一页在线视频| 在线中文高清资源免费观看| ww在线观视频免费观看w| 久久夜色精品国产亚洲AV动态图| 97热久久免费频精品99| 黄色一级视频免费| 91情国产l精品国产亚洲区| 国产自产拍精品视频免费看| 最新亚洲成av人免费看| 亚洲中文字幕无码中文字| 精品国产亚洲男女在线线电影 | 亚洲色欲色欲www| 在线亚洲精品福利网址导航| 最近新韩国日本免费观看|