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

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

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

    java-string類(lèi)型參數(shù)傳遞分析

    Posted on 2010-12-05 16:27 alex_zheng 閱讀(1159) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): java
    上周去一家公司面試,其中一個(gè)面試題是這樣的,判斷下面程序輸出,本人很杯具的寫(xiě)了"changed"
    public class StringArgTest {

        
    private void change(String s){
            s 
    = "changed";
        }
      

        
    private void test(){
            String h 
    = "hi";
            change(h);     

            System.out.println(h);       
        }
        
        
    public static void main(String[] args) {
            StringArgTest st 
    = new StringArgTest();
            st.test();
        }
    回來(lái)后想,在java中參數(shù)傳遞都是值傳遞,如果是對(duì)象的話,傳的是該對(duì)象的引用的值,那么從java運(yùn)行時(shí)的棧數(shù)據(jù)來(lái)看,在調(diào)用test方法的時(shí)候,test的局部變量區(qū)中h的值是hi,然后在執(zhí)行change方法前,s在change的局部變量表的值還是hi,在給s賦值后,s的值變?yōu)閏hanged,但這個(gè)作用范圍是change方法,那么這時(shí)候h的值是什么呢?答案是還是hi,在change方法執(zhí)行完后,指令返回test方法時(shí),test的局部變量區(qū)內(nèi)h的值并沒(méi)有改變。
    對(duì)這個(gè)類(lèi)稍微做下改變
    public class StringArgTest {

        
    private void change(String s){
            s 
    = "changed";
        }
        
    private String change2(String s){
            s 
    = "changed2";
            
    return s;
        }
        
    private void test(){
            String h 
    = "hi";
            change(h);
            String h2 
    = "h2";
            h2 
    = change2(h2);
            System.out.println(h);
            System.out.println(h2);
        }
        
        
    public static void main(String[] args) {
            StringArgTest st 
    = new StringArgTest();
            st.test();
        } 
    }
    通過(guò)命令查看class文件的字節(jié)碼javap -verbose -c -private StringArgTest >~/StringArgTest
    這里假定操作棧為S,局部變量表為L(zhǎng),S0表示操作數(shù)棧頂,L0表示局部變量表的第一個(gè)變量,我們知道jvm執(zhí)行方法時(shí),每個(gè)方法的局部變量表是方法獨(dú)立的
    Compiled from "StringArgTest.java"
    public class com.demo.StringArgTest extends java.lang.Object
      SourceFile: 
    "StringArgTest.java"
      minor version: 
    0
      major version: 
    50
      Constant pool://常量池內(nèi)容,是該類(lèi)的元數(shù)據(jù)
    const #1 = class    #2;    //  com/demo/StringArgTest
    const #2 = Asciz    com/demo/StringArgTest;
    const #3 = class    #4;    //  java/lang/Object
    const #4 = Asciz    java/lang/Object;
    const #5 = Asciz    <init>;
    const #6 = Asciz    ()V;
    const #7 = Asciz    Code;
    const #8 = Method    #3.#9;    //  java/lang/Object."<init>":()V
    const #9 = NameAndType    #5:#6;//  "<init>":()V
    const #10 = Asciz    LineNumberTable;
    const #11 = Asciz    LocalVariableTable;
    const #12 = Asciz    this;
    const #13 = Asciz    Lcom/demo/StringArgTest;;
    const #14 = Asciz    change;
    const #15 = Asciz    (Ljava/lang/String;)V;
    const #16 = String    #17;    //  changed
    const #17 = Asciz    changed;
    const #18 = Asciz    s;
    const #19 = Asciz    Ljava/lang/String;;
    const #20 = Asciz    change2;
    const #21 = Asciz    (Ljava/lang/String;)Ljava/lang/String;;
    const #22 = String    #23;    //  changed2
    const #23 = Asciz    changed2;
    const #24 = Asciz    test;
    const #25 = String    #26;    //  hi
    const #26 = Asciz    hi;
    const #27 = Method    #1.#28;    //  com/demo/StringArgTest.change:(Ljava/lang/String;)V
    const #28 = NameAndType    #14:#15;//  change:(Ljava/lang/String;)V
    const #29 = String    #30;    //  h2
    const #30 = Asciz    h2;
    const #31 = Method    #1.#32;    //  com/demo/StringArgTest.change2:(Ljava/lang/String;)Ljava/lang/String;
    const #32 = NameAndType    #20:#21;//  change2:(Ljava/lang/String;)Ljava/lang/String;
    const #33 = Field    #34.#36;    //  java/lang/System.out:Ljava/io/PrintStream;
    const #34 = class    #35;    //  java/lang/System
    const #35 = Asciz    java/lang/System;
    const #36 = NameAndType    #37:#38;//  out:Ljava/io/PrintStream;
    const #37 = Asciz    out;
    const #38 = Asciz    Ljava/io/PrintStream;;
    const #39 = Method    #40.#42;    //  java/io/PrintStream.println:(Ljava/lang/String;)V
    const #40 = class    #41;    //  java/io/PrintStream
    const #41 = Asciz    java/io/PrintStream;
    const #42 = NameAndType    #43:#15;//  println:(Ljava/lang/String;)V
    const #43 = Asciz    println;
    const #44 = Asciz    h;
    const #45 = Asciz    main;
    const #46 = Asciz    ([Ljava/lang/String;)V;
    const #47 = Method    #1.#9;    //  com/demo/StringArgTest."<init>":()V
    const #48 = Method    #1.#49;    //  com/demo/StringArgTest.test:()V
    const #49 = NameAndType    #24:#6;//  test:()V
    const #50 = Asciz    args;
    const #51 = Asciz    [Ljava/lang/String;;
    const #52 = Asciz    st;
    const #53 = Asciz    SourceFile;
    const #54 = Asciz    StringArgTest.java;

    {
    public com.demo.StringArgTest();//系統(tǒng)默認(rèn)生成的構(gòu)造函數(shù)
      Code:
       Stack
    =1, Locals=1, Args_size=1
       
    0:    aload_0
       
    1:    invokespecial    #8//Method java/lang/Object."<init>":()V
       4:    return
      LineNumberTable: 
       line 
    30

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       
    0      5      0    this       Lcom/demo/StringArgTest;


    private void change(java.lang.String);
      Code:
       Stack
    =1, Locals=2, Args_size=2
       
    0:    ldc    #16//String changed 從常量池壓入changed的引用地址16到S0
       2:    astore_1    //彈出S0,賦值給局部變量L1,此時(shí)s的值是changed
       
    3:    return        //返回到test方法,不返回任何數(shù)據(jù)
      LineNumberTable: 
       line 
    60
       line 
    73

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       
    0      4      0    this       Lcom/demo/StringArgTest;
       
    0      4      1    s       Ljava/lang/String;


    private java.lang.String change2(java.lang.String);
      Code:
       Stack
    =1, Locals=2, Args_size=2
       
    0:    ldc    #22//String changed2
       2:    astore_1    //彈出S0,賦值給局部變量L1,即s
       
    3:    aload_1     //從L1中加載變量到S0
       
    4:    areturn     //返回S0中的引用,即變量s的引用,這里是changed2的索引22
      LineNumberTable: 
       line 
    90
       line 
    103

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       
    0      5      0    this       Lcom/demo/StringArgTest;
       
    0      5      1    s       Ljava/lang/String;


    private void test();
      Code:
       Stack
    =2, Locals=3, Args_size=1
       
    0:    ldc    #25//String hi 從常量池中壓入hi的引用,
       2:    astore_1    //彈出S0,賦值給L1,即h
       
    3:    aload_0     //加載L0到S0,即this的引用
       
    4:    aload_1     //加載L1到S1,即h的引用
       
    5:    invokespecial    #27//Method change:(Ljava/lang/String;)V,此時(shí)test的局部變量表中,h的值仍是hi
       8:    ldc    #29//String h2  壓入h2到S2
       10:    astore_2      //彈出S2,賦值給L2,即h2
       
    11:    aload_0       //加載L0到S2
       
    12:    aload_2       //加載L2到S3
       
    13:    invokespecial    #31//Method change2:(Ljava/lang/String;)Ljava/lang/String;這里方法返回常量區(qū)changed2的引用,壓入S4
       16:    astore_2      //彈出S4即changed2的引用,賦值給L2
       
    17:    getstatic    #33//Field java/lang/System.out:Ljava/io/PrintStream;
       20:    aload_1      //加載L1,即h的引用,對(duì)應(yīng)字符串仍為hi
       
    21:    invokevirtual    #39//Method java/io/PrintStream.println:(Ljava/lang/String;)V
       24:    getstatic    #33//Field java/lang/System.out:Ljava/io/PrintStream;
       27:    aload_2      //加載L2,對(duì)應(yīng)字符串為changed2
       
    28:    invokevirtual    #39//Method java/io/PrintStream.println:(Ljava/lang/String;)V
       31:    return
      LineNumberTable: 
       line 
    130
       line 
    143
       line 
    158
       line 
    1611
       line 
    1717
       line 
    1824
       line 
    1931

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       
    0      32      0    this       Lcom/demo/StringArgTest;
       
    3      29      1    h       Ljava/lang/String;
       
    11      21      2    h2       Ljava/lang/String;


    public static void main(java.lang.String[]);
      Code:
       Stack
    =2, Locals=2, Args_size=1
       
    0:    new    #1//class com/demo/StringArgTest
       3:    dup
       
    4:    invokespecial    #47//Method "<init>":()V
       7:    astore_1
       
    8:    aload_1
       
    9:    invokespecial    #48//Method test:()V
       12:    return
      LineNumberTable: 
       line 
    220
       line 
    238
       line 
    2412

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       
    0      13      0    args       [Ljava/lang/String;
       
    8      5      1    st       Lcom/demo/StringArgTest;


    }
    從上可以看出,change方法里雖然改變了參數(shù)s的值,但是s的作用范圍是change方法,在該方法退出后,test方法里局部變量h的引用并未改變,仍是常量池中hi的索引地址,在調(diào)用change2方法后,test方法局部變量h2的值也隨之改變

    posts - 10, comments - 9, trackbacks - 0, articles - 15

    Copyright © alex_zheng

    主站蜘蛛池模板: 成a人片亚洲日本久久| 亚洲va无码专区国产乱码| 野花高清在线观看免费完整版中文| 可以免费观看的国产视频| 中文毛片无遮挡高清免费| 国产成人1024精品免费| 一本岛v免费不卡一二三区| 又硬又粗又长又爽免费看 | 亚洲av无码专区在线播放| 亚洲一区精品无码| 亚洲中文字幕久久精品无码APP| 国内精品久久久久久久亚洲| 在线A亚洲老鸭窝天堂| 国产亚洲色婷婷久久99精品| 亚洲今日精彩视频| 亚洲色欲www综合网| 亚洲一卡2卡4卡5卡6卡在线99| 国产成人精品日本亚洲专一区| 美女视频黄免费亚洲| 香蕉视频亚洲一级| 亚欧洲精品在线视频免费观看| 国产又黄又爽胸又大免费视频 | 亚洲熟妇自偷自拍另欧美| 亚洲精品中文字幕无码A片老| 久久精品亚洲日本波多野结衣| 在线亚洲精品视频| h片在线观看免费| 久9热免费精品视频在线观看| 综合在线免费视频| 国产精品成人四虎免费视频| 国产成人亚洲综合| 亚洲AV无码国产在丝袜线观看| 亚洲熟妇色自偷自拍另类| 亚洲精品欧美综合四区| 精品久久久久久国产免费了| 一级毛片在线免费看| 午夜老司机免费视频| 国产成人亚洲精品狼色在线| 亚洲精品视频在线播放| 久久亚洲中文字幕无码| a成人毛片免费观看|