1. 程式人生 > >關於JAVA的傳值與引用的理解

關於JAVA的傳值與引用的理解

接上上次的問題 聽說可以用引用來解決那個問題。 如果沒連結的話。請看基礎篇---》JAVA反射的那篇後續寫了這個。引用與反射


通過這個我們發現 或者你自己去測試寫一個類Int 和String  都是final 類感覺很類似。而且內部也沒有什麼方法可以去修改值。

唯獨Stringbuffer 可以修改。這個應該和他們的記憶體儲存的方式有影響。

詳細的內容自己可以百度去找下。方法的內部變數。在使用後自動被系統收回。而不改變方法外的變數值。

這就是引用不到方法外的變數。雖然傳值也傳了。具體的話。有大牛來反駁我的解釋 我虛心接收學習。

開始理解概念上的東西了這裡我就不寫了複製下,

1. 簡單型別是按值傳遞的

  Java方法的引數是簡單型別的時候,是按值傳遞的 (pass by value)。這一點我們可以通過一個簡單的例子來說明:

[java] view plain copy  print?
  1. /*例 1 */
  2. /** 
  3.  * @(#) Test.java 
  4.  * @author fancy 
  5.  */
  6. publicclass Test {  
  7.     publicstaticvoid test(boolean test) {  
  8.         test = ! test;  
  9.         System.out.println("In test(boolean): test = "
     + test);  
  10.     }  
  11.     publicstaticvoid main(String[] args) {  
  12.         boolean test = true;  
  13.         System.out.println("Beforetest(boolean) : test = " + test);  
  14.         test(test);  
  15.         System.out.println("Aftertest(boolean) : test = " + test);  
  16.     }  
  17. }  

執行結果:

[plain]
 view plain copy  print?
  1. Beforetest(boolean) : test = true  
  2. In test(boolean) : test = false  
  3. After test(boolean) : test = true  

  不難看出,雖然在 test(boolean) 方法中改變了傳進來的引數的值,但對這個引數源變數本身並沒有影響,即對 main(String[]) 方法裡的 test 變數沒有影響。那說明,引數型別是簡單型別的時候,是按值傳遞的。以引數形式傳遞簡單型別的變數時,實際上是將引數的值作了一個拷貝傳進方法函式的,那麼在方法函式裡再怎麼改變其值,其結果都是隻改變了拷貝的值,而不是源值。

2. 什麼是引用

  Java是傳值還是傳引用,問題主要出在物件的傳遞上,因為 Java 中簡單型別沒有引用。既然爭論中提到了引用這個東西,為了搞清楚這個問題,我們必須要知道引用是什麼。

  簡單的說,引用其實就像是一個物件的名字或者別名 (alias),一個物件在記憶體中會請求一塊空間來儲存資料,根據物件的大小,它可能需要佔用的空間大小也不等。訪問物件的時候,我們不會直接是訪問物件在記憶體中的資料,而是通過引用去訪問。引用也是一種資料型別,我們可以把它想象為類似 C 語言中指標的東西,它指示了物件在記憶體中的地址——只不過我們不能夠觀察到這個地址究竟是什麼。

  如果我們定義了不止一個引用指向同一個物件,那麼這些引用是不相同的,因為引用也是一種資料型別,需要一定的記憶體空間來儲存。但是它們的值是相同的,都指示同一個物件在記憶體的中位置。比如

[java] view plain copy  print?
  1. Stringa = "Hello";  
  2. String b = a;  

  這裡,a和 b 是不同的兩個引用,我們使用了兩個定義語句來定義它們。但它們的值是一樣的,都指向同一個物件"Hello"。也許你還覺得不夠直觀,因為 String 物件的值本身是不可更改的 (像 b = "World"; b = a; 這種情況不是改變了 "World" 這一物件的值,而是改變了它的引用b 的值使之指向了另一個 String 物件 a)。那麼我們用 StringBuffer 來舉一個例子:

[java] view plain copy  print?
  1. /*例 2 */
  2. /** 
  3.  * @(#) Test.java 
  4.  * @author fancy 
  5.  */
  6. publicclass Test {  
  7.     publicstaticvoid main(String[] args) {  
  8.         StringBuffer a = newStringBuffer("Hello");  
  9.         StringBuffer b = a;  
  10.         b.append(", World");  
  11.         System.out.println("a is "+ a);  
  12.     }  
  13. }  

            執行結果:

[java] view plain copy  print?
  1. ais Hello, World  

  這個例子中 a 和 b 都是引用,當改變了 b 指示的物件的值的時候,從輸出結果來看,a 所指示的物件的值也改變了。所以,a 和b 都指向同一個物件即包含 "Hello" 的一個 StringBuffer 物件。

  這裡我描述了兩個要點:

1.     引用是一種資料型別,儲存了物件在記憶體中的地址,這種型別即不是我們平時所說的簡單資料型別也不是類例項(物件);

2.     不同的引用可能指向同一個物件,換句話說,一個物件可以有多個引用,即該類型別的變數。

3. 物件是如何傳遞的呢

  關於物件的傳遞,有兩種說法,即“它是按值傳遞的”和“它是按引用傳遞的”。這兩種說法各有各的道理,但是它們都沒有從本質上去分析,即致於產生了爭論。

  既然現在我們已經知道了引用是什麼東西,那麼現在不妨來分析一下物件作是引數是如何傳遞的。還是先以一個程式為例:

[java] view plain copy  print?
  1. /*例 3 */
  2. /** 
  3.  * @(#) Test.java 
  4.  * @author fancy 
  5.  */
  6. publicclass Test {  
  7.     publicstaticvoid test(StringBuffer str) {  
  8.         str.append(", World!");  
  9.     }  
  10.     publicstaticvoid main(String[] args) {  
  11.         StringBuffer string = newStringBuffer("Hello");  
  12.         test(string);  
  13.         System.out.println(string);  
  14.     }  
  15. }  

執行結果:  

[java] view plain copy  print?
  1. Hello,World!  

  test(string)呼叫了 test(StringBuffer) 方法,並將 string 作為引數傳遞了進去。這裡 string 是一個引用,這一點是勿庸置疑的。前面提到,引用是一種資料型別,而且不是物件,所以它不可能按引用傳遞,所以它是按值傳遞的,它麼它的值究竟是什麼呢?是物件的地址。

  由此可見,物件作為引數的時候是按值傳遞的,對嗎?錯!為什麼錯,讓我們看另一個例子:

[java] view plain copy  print?
  1. /*例 4 */
  2. /** 
  3.  * @(#) Test.java 
  4.  * @author fancy 
  5.  */
  6. publicclass Test {  
  7.     publicstaticvoid test(String str) {  
  8.         str = "World";  
  9.     }  
  10.     publicstaticvoid main(String[] args) {  
  11.         String string = "Hello";  
  12.         test(string);  
  13.         System.out.println(string);  
  14.     }  
  15. }  

  執行結果:

[plain] view plain copy  print?
  1. 相關推薦

    關於JAVA引用理解

    接上上次的問題 聽說可以用引用來解決那個問題。 如果沒連結的話。請看基礎篇---》JAVA反射的那篇後續寫了這個。引用與反射 通過這個我們發現 或者你自己去測試寫一個類Int 和String  都是final 類感覺很類似。而且內部也沒有什麼方法可以去修

    微信小程式資料引用data變數

    1、在微信小程式中通過點選方法進行變數賦值,可以將數值定義在e.currentTarget.dataset裡 通過定義data-x,將index值進行傳遞 <block wx:for="{{imgUrls}}" wx:key="{{index}}"&g

    Java傳遞引用的區分

    基本型別傳的是值,例如:int,float,double,char,不包括 java.lang.String 物件例項,介面例項傳的是引用,包括java.lang.String。但是我們在通過一個函式傳遞String引數時,為何出來的結果沒有發生改變?如下所示: void

    java中的經典問題:引用

    引數傳遞的祕密 知道方法引數如何傳遞嗎?記得剛開始學程式設計那會兒,老師教導,所謂引數,有形式引數和實際引數之分,引數列表中寫的那些東西都叫形式引數,在實際呼叫的時候,它們會被實際引數所替代。編譯程式不可能知道每次呼叫的實際引數都是什麼,於是寫編譯器的高手就出個辦法,讓實

    Java函式中引用的區別

    1、對於基本資料型別,傳遞到函式中的是源變數的值 看下面例子: public class Value_Index { public static void main(String[] args){

    深入理解PHP中賦引用

    str ring int 之前 不同 重新 small nts 計數 【原文】 先看下面的問題: 1 2 3 4 5 6 7 8 <?php $a = 10;//將常量值賦給變量,會為a分配內存空間 $b = $a;//變量賦值給變量,是不是

    Java學習筆記之物件引用總結

    <strong><span style="font-size:18px;"> public class Test { public static void main(String[] args) { // TODO Auto-generated method s

    java引用

    基礎型別和非集合類的物件都是傳值 集合傳的是引用 class p{ int age; } void changegae(p a){ a.age=2; } int s=1; String x="x"; void changenum(int a){ a=

    php中引用的有什麼區別

    php傳值:在函式範圍內,改變變數值得大小,都不不會影響到函式外邊的變數值。 PHP按引用:在函式範圍內,對值的任何改變,在函式外部也有所體現,因為傳引用傳的是記憶體地址。 <?php //傳值 $a = 1; $b = 2; $b = $a; $a = 3; echo $b.

    java地址

    相信學習過c的朋友們,對於傳值與傳地址比較熟悉,而在java中這樣的術語用的比較少,那麼到底存不存在傳值與傳地址呢? 答案肯定是:存在的!! 做下列總結: 說明:Student student=new Student();中student就可以看作是c裡面的指標

    [UE4]引用

    分享 mage 傳引用 nbsp 參數 就會 com 對象 image 值傳遞是圓形圖標 設置引用需要使用Set by ref函數 對象在藍圖中都是以引用傳遞   對象,不需要額外設置參數類型是傳值還是傳引用。 結構體在藍圖中默認是按值傳遞

    Java 引用的區別

    首先對傳值和傳引用要有個基本的概念 傳值:傳遞的是值的副本。方法中對副本的修改,不會影響到呼叫方。 傳引用:傳遞的是引用的副本,共用一個記憶體,會影響到呼叫方。此時,形參和實參指向同一個記憶體地址。對

    java還是引用

    最近一直在看primer c++,函式一章對c++函式之間傳遞引數有詳細的講解,傳值、傳指標和傳引用的應用與區別都講得很清楚,以前一直用java,由於java沒有指標,當時也沒有引用這個概念,所以沒有對java引數的傳遞有過多的思考,現在搞清楚了c++傳遞引數的機制,自然就會

    java引用的問題,String型別不會改變!

    java傳值和傳引用的問題,我們都知道,類,陣列,介面和String等等引用資料型別都是傳引用,在方法中修改了引用型別的變數會改變原變數,而像基本資料型別都是傳值,所以不會改變,但是String型別也是

    JAVA中物件的賦引用

    前言 最近在學習紅黑樹,當我嘗試不使用遞迴來實現時,發現自己的大腦陷入了混亂。 究其原因,是對JAVA中的基本型別和引用型別有所誤解。 特地重新搜尋+實踐一番,漲個姿勢。 一番折騰 先找個物件過年 class Node {

    java中函數傳引用問題

    輸出 set 驗證 臨時對象 輸出結果 引用 chan sta 賦值運算 從C++轉java,在使用函數傳對象時,碰到一點問題,今天特意驗證了一下: public class App { public static void doubleTest(double

    Python的函式引用簡解

    Python到底值傳值還是傳引用? 先看兩段程式碼 程式碼1: 1 2 3 4 5 6 7 >>> a=3 >>> def f(b): ...     b=1 ...     >>> f

    【iOS】代理塊代碼

    ring 方法 nslog 設置代理 轉載 adf delegate alloc 代理傳值 主線程與子線程常常須要進行數據的傳遞。不同的類之間,不同的控制器之間都須要。 並且常常須要監聽一個動作的完畢。而後才去做對應事件。(代理是一對一的關系)。 一、代理傳值 代理

    分享 span logs .cn 基本類型 傳值 str image mage 基本類型傳值 引用類型傳址 傳值與傳址

    JSONPHP接收的幾種情況

    利用Chrome的後臺網路,分析了通過JQuery的$.ajax()把 json 資料 post 給 PHP時的幾種情況: 無法在PHP中通過$_POST 以及 $_REQUEST 獲取json資料,即 $json = $_POST['json'];