1、javascript中的参数传递:值传递

(1)在js函数传递中,当基本类型(number, string, boolean, null, undefined, symbol)变量作为参数传递时,函数内部对参数的任何操作都不会改变变量的值。 

(2)当object类型变量作为参数传递时,函数内部对参数的操作会影响变量的值,除非函数内部对参数重新赋值(任何类型的值)。   


<!DOCTYPE html>
 <html>
 <head>
     <title></title>
     <meta  charset="utf-8"/>
 </head>
 <body>
     <p>welcome </p>
     <script language="JavaScript">
         var obj = {};
         obj.inner = 10;
         var num = 10;
         var str = 'Hello';
         var boo = true;
         var oth = null;
         var und = undefined;
         var sym = Symbol('foo');
         function passingobject(myobj){
             myobj.inner = 1+myobj.inner;
         }
         function passingvalue(myValue){
             switch (typeof myValue){
                 case 'number':
                     myValue = myValue+1;
                     break;
                 case 'string':
                     myValue = 'I am a new string now!';
                     break;
                 case 'boolean':
                     myValue = false;
                     break;
                 default :
                 case 'number':
                     myValue = 'Null,Undefined,or Symbol';
             }
         }
         console.log("before num"+num);//10
         passingvalue(num);
         console.log("after num"+num);//10
         console.log("before str = " + str); // before str = Hello  
         passingvalue(str); 
         console.log("after str = " + str);  // after str = Hello   
         console.log("before boo = " + boo); // before boo = true   
          passingvalue(boo); 
         console.log("after boo = " + boo);  // after boo = true   
          console.log("before oth = " + oth); // before oth = null   
           passingvalue(oth); 
         console.log("after oth = " + oth);  // after oth = null   
          console.log("before und = " + und); // before und = undefined   
           passingvalue(und); 
         console.log("after und = " + und);  // after und = undefined   
          console.log(sym); // Symbol(foo)   
           passingvalue(sym);
         console.log(sym); // Symbol(foo) 
         console.log("before obj.inner = " + obj.inner); //www.baiyuewang.net before obj.inner = 10 
         passingobject(obj); // after obj.inner = 11   
          console.log("after obj.inner = " + obj.inner);
         function changeStuff(a, b, c) 
          {
               a = a * 10;
               b.item = "changed";  
               c = {item: "changed"};  
           } 
         var num = 10;
         var obj1 = {item: "unchanged"}; 
          var obj2 = {item: "unchanged"};
         console.log(obj1.item);//unchanged  
         console.log(obj2.item); // unchanged 
         console.log(num);//10
         changeStuff(num, obj1, obj2);
         console.log(num);//10
          console.log(obj1.item); // changed 
          console.log(obj2.item); // unchanged
     </script>
 </body>
 </html>


2、java中的参数传递:值传递

(1)对于基本类型变量作为参数传递时,java是传递值的副本,函数内部对参数的任何操作都不会改变变量的值。 

(2)对于一切对象型变量,java都是传递引用的副本,函数内部对参数的操作会影响变量的值,除非函数内部对参数重新赋值(任何类型的值)。  要注意String类型,因为属于final类型,所以总是不会被影响

package com.shenzhoufu;
 import java.util.*;
 public class Reference {
public static void main(String[] args){
//————————boolean——————————————————————————————
boolean b = true;
System.out.println("unchanged:"+b);//true
testBoo(b);//false
System.out.println("changed:"+b);//true
//————————String——————————————————————————————
String str = ",world!";
System.out.println("unchanged:"+str);//,world!
testString(str);//Hello
System.out.println("changed:"+str);//,world!
//————————————StringBuffer——————————————————————
StringBuffer strb = new StringBuffer(",world!");
System.out.println("unchanged:"+strb);//,world!
testStringBuffer(strb);//,world!hello
System.out.println("changed:"+strb);//,world!hello
}
//基本类型
public static void testBoo(boolean b){
b = !b;
System.out.println("changing(in test):"+b);
}
//String类型
public static void testString(String s){
String string = "Hello";
System.out.println("newString:"+string);
}
//StringBuffer 对象
public static void testStringBuffer(StringBuffer s){
s.append("hello");
System.out.println("changing(in test)StringBuffer:"+s);
}
 }

1、对象是按引用传递的
2、Java 应用程序有且仅有的一种参数传递机制,即按值传递
3、按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本
4、按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本

class Test01 

   { 

   public static void main(String[] args) 

   { 

   StringBuffer s= new StringBuffer("good"); 

   StringBuffer s2=s; 

   s2.append(" afternoon."); 

   System.out.println(s); 

   } 

   }


  对象s和s2指向的是内存中的同一个地址因此指向的也是同一个对象。


  如何解释“对象是按引用传递的”的呢?


  这里的意思是进行对象赋值操作是传递的是对象的引用,因此对象是按引用传递的,有问题吗?


  程序运行的输出是:


 

good afternoon.



  这说明s2和s是同一个对象。


  这里有一点要澄清的是,这里的传对象其实也是传值,因为对象就是一个指针,这个赋值是指针之间的赋值,因此在java中就将它说成了传引用。(引用是什么?不就是地址吗?地址是什么,不过就是一个整数值)


class Test2
  {
  public static void main(String[] args)
  {   StringBuffer s= new StringBuffer("good");
StringBuffer s2=new StringBuffer("bad"); 
test(s,s2);
System.out.println(s);// goodhah
System.out.println(s2);//bad为什么呢????有大神能解释么
   }
public static void test(StringBuffer s,StringBuffer s2) {
System.out.println(s);//good
System.out.println(s2);//bad
s2=s; 
s=new StringBuffer("new"); 
System.out.println(s);//new
System.out.println(s2);//good
s.append("hah"); 
s2.append("hah"); 
System.out.println(s);//newhah
System.out.println(s2);//goodhah
}}

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

不同的操作系统不太一样,但一般内存都分为4个区域:

1)heap(堆):存放new出来的对象

2)stack(栈):存放局部变量

3)data segment(数据区):静态变量 和 字符串常量

4)code segment(代码区):存放代码 

Java中进行方法调用的时候传递参数时,遵循值传递的原则:

1)基本数据类型,传递的是数据的拷贝

2)引用数据类型,传递的是传递的引用地址的拷贝,而不是该对象本身

例子:

public class Test {
     void f(int j) {
           System.out.println(j);
     }
    void ff(String ss) {
           System.out.println(ss);
    }
    public static void main(Stirng[] args) {
             int i = 100;
             String s = "hello";
            Test t = new Test();
             t.f(i);
             t.ff(s);
        }
}

内存中的执行过程:

当mian方法开始执行的时候  

(1)int i = 100;  栈中分配一块空间,存放变量i,值为100,基本数据类型只占一块空间;

(2)String s = "hello"; "hello"是字符串常量,分配在data区,字符串常量为String类的一个对象,s指向了这个"hello"对象,这就是引用数据类型,在内存中占两块空间;有点形象思维:一提引用类型,就是一块内存指向另一块内存s可以被叫做:引用、引用变量、引用地址,其实s就是一个指针,在这里不用钻牛角尖,你就知道s是一个引用,s的值是一个地址,根据这个地址就可以找到一个对象就ok了

(3)Test t = new Test(); 同理,栈中的引用t指向了堆中new出来的这个Test对象;

(4)t.f(i);  方法的形参属于局部变量,所以在调用f方法的时候,栈内存分配一个int型的变量j,将i的值当做实参传递过去,i的值是100,现在将100拷贝给了j,那么j的值就是100,这就是楼主说的“值传递”,接着打印,最后方法结束,为该方法分配的局部变量立刻全部清空,那么Stack中这个j消失了;

(5)t.ff(s);  调用ff方法的时候,栈内存分配一个String型的变量ss,将s的值当做实参传递过去,s指向了"hello"对象,s的值是一个地址,现在将这个地址拷贝给了ss,那么ss也就指向这个"hello"了这就是楼主说的"引用传递",现在s 和 ss 两个引用 同时指向了"hello"对象,然后打印ss,最后方法结束,栈中这个ss被清除;

现在main方法执行结束,为main方法分类的局部变量清除,i,s,t全部消失,data区的符串常量"hello"和堆内存的Test对象,由于没有任何引用指向他们了,就会被垃圾收集器回收