4.2 方法所屬性、方法參數傳遞機制、形參個數可變的方法

1、方法的所屬性

  方法由傳統的函數發展而來,方法與傳統的函數顯著不一樣:在結構化編程中,函數是一等公民,這個程序由一個個函數組成;在面向對象編程語言裏,類纔是一等公民,整個系統由一個個類組成。所以在Java語言裏,方法不能獨立存在,方法必須屬於類或對象。編程

方法的所屬性:
(1)方法相似於函數。但與函數不一樣的是,方法不能存在,方法必須定義在類裏面。
(2)方法必定要有執行者,必須經過類或對象來調用方法。從邏輯上來看,該方法屬於類自己,應該用類來調用
    若是該方法有static修飾,該方法屬於類自己,應該用類調用;
    若是該方法無static修飾,該方法屬於對象自己,應該用對象調用
【規則】若是調用同一個類中方法,能夠省略調用者,此時系統會默認添加調用者。若是方法是無static方法,添加this做爲默認調用者;若是方法是static方法,添加類做爲調用者。數組

 1 class Method_attribute 
 2 {
 3     //定義一個普通方法
 4     public void nonStaticMethod()
 5     {
 6         System.out.println("這是一個普通方法");
 7     }
 8 
 9     //定義一個static方法
10     public static void StaticMethod()
11     {
12         System.out.println("這是一個類方法");
13     }
14 
15     //在同一個類中一個方法調用另一個方法
16     public void test()
17     {
18 
19         this.nonStaticMethod();
20         this.StaticMethod();
21         StaticMethod();//省略的是主調類
22     }
23     public static void main(String[] args) 
24     {
25         var p=new Method_attribute();
26         //此時test()方法中的兩個this表明對象p
27         p.test();        
28     }
29 }
30 ---------- 運行Java捕獲輸出窗 ----------
31 這是一個普通方法
32 這是一個類方法
33 這是一個類方法
34 
35 輸出完成 (耗時 0 秒) - 正常終止

 2、方法參數的傳遞機制

Java裏方法是不能獨立存在的,調用方法時必須使用類或對象做爲主調者。若是聲明方法時,包含了形參聲明,則調用方法時必須給這些形參指定參數值,調用參數時傳給形參參數值也稱爲實參。編程語言

Java裏面參數傳遞方式只有一種:值傳遞。所謂值傳遞,就是將實際參數的副本(複製品)傳入方法內,而參數自己不會受到影響。函數

class ParamTransferTest 
{
    public static void swap(int a,int b)
    {
        //實現變量a和b的值交換
        //定義一個臨時變量來保存a的值
        var temp=a;
        a=b;
        b=temp;
        System.out.println("swap方法裏,a的值爲:"+a+",b的值爲:"+b);
    }
    public static void main(String[] args) 
    {
        int a=6;
        int b=9;
        swap(a,b);
        System.out.println("交換結束後,a的值爲:"+a+",b的值爲:"+b);
    }
}
---------- 運行Java捕獲輸出窗 ----------
swap方法裏,a的值爲:9,b的值爲:6
交換結束後,a的值爲:6,b的值爲:9

輸出完成 (耗時 0 秒) - 正常終止

 Java程序從main()方法開始執行,main()方法開始定義了a、b兩個局部變量,如圖所示:this

 程序從main()函數開始執行,當程序進入swap()方法時,系統分配了兩個棧區,將mian()方法中的變量a、b的副本傳入swap()方法,而不是a、b自己。spa

程序在swap()方法中,進行變量a、b交換的值,交換結束後,內存中的存儲狀況:code

兩個示意圖能夠發現,mian()方法棧區中a、b值並未發生改變,程序只改變swap()棧區中的變量a、b。這就是值傳遞的實質:當系統開始執行方法時,系統爲形參初始化,就是把實參變量的值賦給方法的形參變量,方法裏操做的並非實參變量。對象

再看一個例子:blog

 1 class DataWrap
 2 {
 3     int a;
 4     int b;
 5 }
 6 
 7 public class ReferenceTransferTest 
 8 {
 9     public static void swap(DataWrap dw)
10     {
11         //下面實現的dw的兩個成員的變量值的交換
12         var temp=dw.a;
13         dw.a=dw.b;
14         dw.b=temp;
15         System.out.println("swap()方法裏,a成員變量的值是:" + dw.a + ",b成員變量的值是:"+dw.b);
16     }
17 
18     public static void main(String[] args) 
19     {
20         var dw=new DataWrap();
21         dw.a=6;
22         dw.b=9;
23         swap(dw);
24         System.out.println("swap()方法裏,a成員變量的值是:"+dw.a+",b成員變量的值是:"+dw.b);
25     }
26 }
27 ---------- 運行Java捕獲輸出窗 ----------
28 swap()方法裏,a成員變量的值是:9,b成員變量的值是:6
29 swap()方法裏,a成員變量的值是:9,b成員變量的值是:6
30 
31 輸出完成 (耗時 0 秒) - 正常終止

 上面結果swap()方法裏和mian()方法裏的兩個變量a、b都發生了改變。這很容易產生錯覺:調用swap()方法時,傳入的時dw自己,而不是它的複製品。內存

下面分析一下程序執行的過程:

(1)程序從mian()方法開始執行:

var dw=new DataWrap();
dw.a=6;
dw.b=9;

這裏建立了一個DataWrap對象,並賦給引用變量dw。堆內存保存該對象自己,棧內存保存的該對象的引用變量。

 

(2)執行swap(dw); 

接下來main()方法開始調用swap()方法,mian(0方法並未結束,系統會爲main()和swap()開闢兩個棧區,用於存放mian()和swap()方法裏的局部變量。調用swap(0方法時,dw做爲實參傳入swap()方法,一樣採用值傳遞:把main()方法裏的dw變量賦值給swap()方法裏的dw形參,從而完成swap()方法的dw形參初始化。下圖顯示main()方法中實參dw傳入swap()方法後的存儲示意圖:

 

 系統只複製了dw變量,但未複製DataWrap對象。

  無論程序在swap()方法中仍是在mian()方法的操做dw變量時,實際操做的都是堆內存中的DataWrap對象,他們引用的是同一個變量。所以在swap()方法中交換了dw所引用的a、b兩個成員變量後,可看到在main()方法中dw引用變量引用的a、b變量的值也發生了改變。

 

 實際上,咱們在建立swap()方法時,將

 public static void swap(DataWrap dw);中的dw換個符號表示理解起來就更容易,不易混淆。

3、形參個數可變的方法

Java容許定義形參個數可變的參數,從而容許爲方法指定數量不肯定的形參。若是在定義方法時,在最後一個形參的類型後增長三點(...),則表示該形參能夠接受多個參數值,多個參數被看成數組傳入。

 1 class  VarArgs
 2 {
 3     public void test(int a,String... names)
 4     {
 5         System.out.println("a參數:"+a);
 6         System.out.println("names數組的長度:"+names.length);
 7         for(int i=0;i<names.length;i++)
 8         {
 9             System.out.println(names[i]);
10         }
11     }
12     public static void main(String... args) 
13     {
14         VarArgs va=new VarArgs();
15         va.test(2,"efdf","fdfs","fjgd");
16         va.test(34,new String[]{"孫悟空","豬八戒"});
17     }
18 }
19 class  VarArgs
20 {
21     public void test(int a,String... names)
22     {
23         System.out.println("a參數:"+a);
24         System.out.println("names數組的長度:"+names.length);
25         for(int i=0;i<names.length;i++)
26         {
27             System.out.println(names[i]);
28         }
29     }
30     public static void main(String... args) 
31     {
32         VarArgs va=new VarArgs();
33         va.test(2,"efdf","fdfs","fjgd");
34         va.test(34,new String[]{"孫悟空","豬八戒"});
35     }
36 }
37 ---------- 運行Java捕獲輸出窗 ----------
38 a參數:2
39 names數組的長度:3
40 efdf
41 fdfs
42 fjgd
43 a參數:34
44 names數組的長度:2
45 孫悟空
46 豬八戒
47 
48 輸出完成 (耗時 0 秒) - 正常終止

va.test(2,"efdf","fdfs","fjgd");   va.test(34,new String[]{"孫悟空","豬八戒"});
這兩種多形參傳入方法均可以,可是第一種方法更加簡潔。

類型[] 形參名

類型...寫法的好處是:
調用方法時更加方便,便可直接傳入多個元素,系統會自動將它們封裝爲數組
也可直接傳入數組
肯定:類型... 這種寫法只能做爲形參列表的最後一個形參
【暗示】一個方法只能由一個形參個數可變的形參

再看一個例子:

 1 class VarIntTest 
 2 {
 3     public int add(int... num)
 4     {
 5         int result=0;
 6         for (int i=0;i<num.length;i++)
 7         {
 8             result+=num[i];
 9         }
10         return result;
11     }
12     public static void main(String[] args) 
13     {
14         var p=new VarIntTest();
15         System.out.println(p.add(1,2,3,4));
16     }
17 }
18 ---------- 運行Java捕獲輸出窗 ----------
19 10
20 
21 輸出完成 (耗時 0 秒) - 正常終止
相關文章
相關標籤/搜索