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

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

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

    精彩的人生

    好好工作,好好生活

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

    不知道這個標題是否讓讀者產生一種想打我的沖動。至少今天我的主管被我用這個小把戲詫異了一把,當他看到"hi there".equals("cheers !") 的結果居然是true時,臉上的表情實在是可愛。

    OK,言歸正傳。System.out.println("hi there".equals("cheers !")); 這個看來再顯然不過的句子,輸出的結果居然是true。聰明的讀者,你知道是為什么嗎?如果一時還猜不出來,給你一點提示:

    1、Java語言規范規定,同一個程序中任何相同的字符串常量(literal string)都只是同一個String對象的不同引用,不論它們是否在同一個類、同一個包中。

    2、Java語言規范規定,由常量表達式計算得到的String對象將在編譯期被求值,并在運行時被作為字符串常量對待;在運行時計算得到的String對象將是一個完全獨立的新對象。

    如果你仍然不明就里,或者想知道這個把戲實現的細節,請看下面這篇來自artima的webLog

    ——————————————————

    Artima Weblogs
    "hi there".equals("cheers !") == true
    by Heinz Kabutz
    May 21, 2003
    Summary
    Java Strings are strange animals. They are all kept in one pen, especially the constant strings. This can lead to bizarre behaviour when we intentionally modify the innards of the constant strings through reflection. Join us, as we take apart one of Java's most prolific beasts.

    Whenever we used to ask our dad a question that he could not possibly have known the answer to (such as: what's the point of school, dad?) he would ask back: "How long is a piece of string?"

    Were he to ask me that now, I would explain to him that String is immutable (supposedly) and that it contains its length, all you have to do is ask the String how long it is. This you can do by calling length().

    OK, so the first thing we learn about Java is that String is immutable. It is like when we first learn about the stork that brings the babies? There are some things you are not supposed to know until you are older! Secrets so dangerous that merely knowing them would endanger the fibres of electrons pulsating through your Java Virtual Machine.

    So, are Strings immutable?

    Playing with your sanity - Strings

    Have a look at the following code:

    public ? class ?MindWarp? {
    ??
    public ? static ? void ?main(String[]?args)? {
    ????System.out.println(
    ??????
    " Romeo,?Romeo,?wherefore?art?thou?oh?Romero? " );
    ??}

    ??
    private ? static ? final ?String?OH_ROMEO? =
    ????
    " Romeo,?Romeo,?wherefore?art?thou?oh?Romero? " ;
    ??
    private ? static ? final ?Warper?warper? = ? new ?Warper();
    }


    If we are told that the class Warper does not produce any visible output when you construct it, what is the output of this program? The most correct answer is, "you don't know, depends on what Warper does". Now THERE's a nice question for the Sun Certified Java Programmer Examination.

    In my case, running "java MindWarp" produces the following output

    C:> java MindWarp <ENTER>
    Stop this romance nonsense, or I'll be sick
    

    And here is the code for Warper:

    												
    import ?java.lang.reflect. * ;
    public ? class ?Warper? {
    ??
    private ? static ?Field?stringValue;
    ??
    static ? {
    ????
    // ?String?has?a?private?char?[]?called?"value"
    ????
    // ?if?it?does?not,?find?the?char?[]?and?assign?it?to?valuetry?{
    ??????stringValue? = ?String. class .getDeclaredField( " value " );
    ????}
    ? catch (NoSuchFieldException?ex)? {
    ??????
    // ?safety?net?in?case?we?are?running?on?a?VM?with?a
    ??????
    // ?different?name?for?the?char?array.
    ??????Field[]?all? = ?String. class .getDeclaredFields();
    ??????
    for ?( int ?i = 0 ;?stringValue? == ? null ? && ?i < all.length;?i ++ )? {
    ????????
    if ?(all[i].getType().equals( char []. class ))? {
    ??????????stringValue?
    = ?all[i];
    ????????}

    ??????}

    ????}

    ????
    if ?(stringValue? != ? null )? {
    ??????stringValue.setAccessible(
    true );? // ?make?field?public
    ????}

    ??}

    ??
    public ?Warper()? {
    ????
    try ? {
    ??????stringValue.set(
    ????????
    " Romeo,?Romeo,?wherefore?art?thou?oh?Romero? " ,
    ????????
    " Stop?this?romance?nonsense,?or?I'll?be?sick " .
    ??????????toCharArray());
    ??????stringValue.set(
    " hi?there " ,? " cheers?! " .toCharArray());
    ????}
    ? catch (IllegalAccessException?ex)? {} ? // ?shhh
    ??}

    }

    How is this possible? How can String manipulation in a completely different part of the program affect our class MindWarp?

    To understand that, we have to look under the hood of Java. In the language specification it says in ?3.10.5:

    "Each string literal is a reference (?4.3) to an instance (?4.3.1, ?12.5) of class String (?4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (?15.28)-are "interned" so as to share unique instances, using the method String.intern."

    The usefulness of this is quite obvious, we will use less memory if we have two Strings which are equivalent pointing at the same object. We can also manually intern Strings by calling the intern() method.

    The language spec goes a bit further:

    1. Literal strings within the same class (?8) in the same package (?7) represent references to the same String object (?4.3.1).
    2. Literal strings within different classes in the same package represent references to the same String object.
    3. Literal strings within different classes in different packages likewise represent references to the same String object.
    4. Strings computed by constant expressions (?15.28) are computed at compile time and then treated as if they were literals.
    5. Strings computed at run time are newly created and therefore distinct.
    6. The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.

    This means that if a class in another package "fiddles" with an interned String, it can cause havoc in your program. Is this a good thing? (You don't need to answer ;-)

    Consider this example

    												
    public ? class ?StringEquals? {
    public ? static ? void ?main(String[]?args)? {
    ??System.out.println(
    " hi?there " .equals( " cheers?! " ));
    }

    private ? static ? final ?String?greeting? = ? " hi?there " ;
    private ? static ? final ?Warper?warper? = ? new ?Warper();
    }

    Running this against the Warper produces a result of true, which is really weird, and in my opinion, quite mind-bending. Hey, you can SEE the values there right in front of you and they are clearly NOT equal!

    BTW, for simplicity, the Strings in my examples are exactly the same length, but you can change the length quite easily as well.

    Last example concerns the HashCode of String, which is now cached for performance reasons mentioned in "Java Idiom and Performance Guide", ISBN 0130142603. (Just for the record, I was never and am still not convinced that caching the String hash code in a wrapper object is a good idea, but caching it in String itself is almost acceptable, considering String literals.)

    												
    public ? class ?CachingHashcode? {
    ??
    public ? static ? void ?main(String[]?args)? {
    ????java.util.Map?map?
    = ? new ?java.util.HashMap();
    ????map.put(
    " hi?there " ,? " You?found?the?value " );
    ????
    new ?Warper();
    ????System.out.println(map.get(
    " hi?there " ));
    ????System.out.println(map);
    ??}

    ??
    private ? static ? final ?String?greeting? = ? " hi?there " ;
    }

    The output under JDK 1.3 is:

    You found the value
    {cheers !=You found the value}
    

    Under JDK 1.2 it is

    null
    {cheers !=You found the value}
    

    This is because in the JDK 1.3 SUN is caching the hash code so if it once is calculated, it doesn't get recalculated, so if the value field changes, the hashcode stays the same.

    Imagine trying to debug this program where SOMEWHERE, one of your hackers has done a "workaround" by modifying a String literal. The thought scares me.

    The practical application of this blog? Let's face it, none.

    This is my first blog ever, I would be keen to hear what you thought of it?



    摘自:http://www.daima.com.cn/Info/55/Info14695/

    posted on 2006-04-03 11:23 hopeshared 閱讀(522) 評論(1)  編輯  收藏 所屬分類: Java

    Feedback

    # re: 轉:[Java細節]"hi there".equals("cheers !") == true 2006-04-03 20:24 wolfsquare2
    樓主你搞錯了吧?
    System.out.println("hi there".equals("cheers !"));
    輸出的是false
    已經在Eclipse+JDK1.4下驗證過了。  回復  更多評論
      

    主站蜘蛛池模板: 亚洲AV无码久久精品狠狠爱浪潮| 亚洲福利在线播放| 噜噜噜亚洲色成人网站∨| 97超高清在线观看免费视频| 国产亚洲精aa成人网站| 一区二区三区在线免费观看视频| 国产伦一区二区三区免费 | 亚洲av永久无码精品国产精品| 中文在线免费观看| 亚洲国产精品无码久久久蜜芽 | 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 天堂亚洲免费视频| 亚洲精品视频久久久| 狠狠躁狠狠爱免费视频无码| 久久精品国产亚洲一区二区三区| 亚洲免费视频一区二区三区| 精品国产亚洲一区二区三区| 99精品视频免费在线观看| 色在线亚洲视频www| 国产午夜无码视频免费网站| 永久免费无码日韩视频| 亚洲日韩精品A∨片无码| 99re在线视频免费观看| 亚洲人精品亚洲人成在线| 四虎永久免费地址在线网站| www成人免费视频| 久久亚洲春色中文字幕久久久| 黄色免费网站网址| 精品在线免费视频| 国产V亚洲V天堂A无码| 色窝窝免费一区二区三区| 无人视频在线观看免费播放影院| 亚洲国产成人一区二区精品区| 亚洲一区二区三区免费观看| 国产精品亚洲一区二区三区久久| 亚洲AV无码一区东京热| 毛片免费视频在线观看| 在线免费播放一级毛片| 亚洲最大av资源站无码av网址| 中文字幕亚洲一区| 中文字幕无码不卡免费视频|