1. 程式人生 > >(第2講)javascript中的引數傳遞和java中的引數傳遞

(第2講)javascript中的引數傳遞和java中的引數傳遞

 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物件,由於沒有任何引用指向他們了,就會被垃圾收集器回收