Java中传值和传址

本文用一下代码说明: java

Java代码  收藏代码 app

简单字符串String: 函数

  1. package luojing;  
  2. public class StringDemo  
  3. {  
  4.     public static void main(String[]args)  
  5.     {  
  6.         String str=new String("hello");  
  7.         //调用函数改变str的值  
  8.         change(str);  
  9.         System.out.println(str);  
  10.           
  11.     }  
  12.       
  13.     public static void change(String str1)  
  14.     {  
  15.         str1+="luojing";  
  16.     }  
  17. }  
程序执行结果:  hello

StringBuffer: this

  1. public class StringDemo  
  2. {  
  3.     public static void main(String[]args)  
  4.     {  
  5.         StringBuffer str=new StringBuffer("hello");  
  6.         //调用函数改变str的值  
  7.         change(str);  
  8.         System.out.println(str);  
  9.           
  10.     }  
  11.       
  12.     public static void change(StringBuffer str1)  
  13.     {  
  14.         str1.append("luojing");  
  15.     }  
  16. }  
程序运行结果 :hello luojing        这个时候str的内容就改变了。


将上面的StringBuffer换成咱们本身定义的对象: spa

  1. public class test  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         Demo demo=new Demo("hello");  
  6.         //调用函数该变demo.name的值  
  7.         change(demo);  
  8.         System.out.println(demo.getName());  
  9.       
  10.     }  
  11.       
  12.     public static void change(Demo d)  
  13.     {  
  14.         d.setName("luojing");  
  15.     }  
  16.   
  17. }  
  18.   
  19. class Demo  
  20. {  
  21.     private String name;  
  22.       
  23.     public Demo(String s)  
  24.     {  
  25.         name=s;  
  26.     }  
  27.     public String getName()  
  28.     {  
  29.         return name;  
  30.     }  
  31.     public void setName(String str)  
  32.     {  
  33.         name=str;  
  34.     }  
  35. }  
程序运行结果: luojing  和咱们使用StringBuffer对象是效果相同。

咱们再对change()方法作一些修改: .net

  1. package luojing;  
  2. public class test   
  3. {  
  4.     public static void main(String[] args)   
  5.     {  
  6.         Demo demo=new Demo("hello");  
  7.         //调用函数该变demo.name的值  
  8.         change(demo);  
  9.         System.out.println(demo.getName());  
  10.       
  11.     }  
  12.       
  13.     public static void change(Demo d)  
  14.     {  
  15.         Demo d1=new Demo("hello java");  
  16.         d=d1;     
  17.     }  
  18.   
  19. }  
  20.   
  21. class Demo  
  22. {  
  23.     private String name;  
  24.       
  25.     public Demo(String s)  
  26.     {  
  27.         name=s;  
  28.     }  
  29.     public String getName()  
  30.     {  
  31.         return name;  
  32.     }  
  33.     public void setName(String str)  
  34.     {  
  35.         name=str;  
  36.     }  
  37. }  
运行结果: hello
     能够看到,虽然咱们在change()方法中对d进行了改变,而实际的对象demo并无改变。


  1. class Foo {  
  2.    private int x;  
  3.    public Foo(int x) {  
  4.       this.x = x;  
  5.     }  
  6.     public void setX(int x) {  
  7.        this.x = x;  
  8.     }  
  9.     public int getX() {  
  10.        return x;  
  11.     }  
  12. }  
  13.   
  14. public class Submit {  
  15.     static Foo fooBar(Foo foo) {  
  16.         foo = new Foo(100);  
  17.         return foo;  
  18.    }  
  19.    
  20.     public static void main(String[] args) {  
  21.         Foo foo = new Foo(300);  
  22.         System.out.print(foo.getX() + "-");  
  23.    
  24.         Foo fooFoo = fooBar(foo);  
  25.         System.out.print(foo.getX() + "-");  
  26.         System.out.print(fooFoo.getX() + "-");  
  27.    
  28.         foo = fooBar(fooFoo);  
  29.         System.out.print(foo.getX() + "-");  
  30.         System.out.print(fooFoo.getX());  
  31.     }  
  32. }  



What is the output of the program shown in the exhibit? 
A. 300-100-100-100-100 
B. 300-300-100-100-100 
C. 300-300-300-100-100 
D. 300-300-300-300-100 

Answer: B 

涉及知识点: 
1.Java中的参数传递有传值和传址两种; 
2.基本类型和String型做为参数时,为传值方式,只把值传入方法,无论在方法中怎么处理这个参数,原值不变; 
3.其余引用类型做为参数时,为传址方式,将指向内存中的地址传入方法,方法中此内存地址中的值发生变化时,原值也会改变; 
4.例外: 
    (1)若是引用类型的对象经过传址方式将其指向内存中的地址传入方法后,方法中使用new关键字从新给参数赋值时,会在内存中从新开辟空间,参数指向新的内存空间,此时参数和原对象指向的就不是同一个地址了,参数值的变化不会改变原值; 
    (2)String型是引用类型,可是String型做为参数,是传值方式,能够经过如下两种方式来理解: 
        <1>String本质上是基本类型的char[],基本类型做为参数时,为传值方式; 
        <2> 字符串在内存中是存储在堆中的一个常量,String对象指向内存中这个常量的地址,经过传址方式将地址传入方法后,方法中若是经过字符串给参数赋值,则会从新在堆中建立一个字符串常量,并指向这个地址,原值依然指向原来的字符串常量地址,参数值的变化不会改变原值,若是经过new关键字给参数赋值,参见 (1)中的解释。 


解析: 
1.“Foo foo = new Foo(300);”,此时foo.getX()的值为300; 
2.“Foo fooFoo = fooBar(foo);”,由于Foo是引用类型,main方法中的foo经过传址的方式将其指向的地址传给fooBar方法中的foo,此时两个foo指向同一个地址,foo.getX()的值都为300;经过“new Foo(100)”给fooBar方法中的foo赋值后,该foo从新指向了一个新的地址,foo.getX()的值为新地址中的值100,而main方法中的foo仍然指向原来的地址,foo.getX()的值没有改变,仍为 300;fooBar将foo的值返回给fooFoo,所以fooFoo.getX()的值为100; 
3.“foo = fooBar(fooFoo);”,同2中的解释,foo.getX()的值变为100,fooFoo.getX()的值没有变化,仍为100;