方法及重載

      在〈方法及重載〉中尚無留言

目的

一長串的程式碼中, 常有某些部份的功能是一樣的, 或者是長的差不多. 這些都稱為重複(duplication)的程式碼. 如下面藍色的部份, 完全一模一樣, 同樣是在列印陣列

public static void main(String[] args){
        int n=50000;
        int d[]=new int[n];
        getData(d);
        for (int i=0;i<d.length;i++){
            System.out.printf("%d ", d[i]);
        }
        System.out.println();
        long t1=System.nanoTime();//目前系統時間, 精準到奈秒
        sort(d);
        long t2=System.nanoTime();
        System.out.println("總花費 : "+(t2-t1)/1000.0f+"微秒");
        for (int i=0;i<d.length;i++){
            System.out.printf("%d ", d[i]);
        }
        System.out.println();
}

重複的代碼是程式的忌諱, 當某個地方要更改時, 比如希望改成
System.out.printf(“%d, “, d[i]);
也就是希望印出來多一個 “,” 那麼此時除了上面那一部份要更改, 下面的那一部份也要再更改一次.

當程式碼愈來愈長, 重複的地方分散相隔好幾百行, 這下要足一尋找, 比大海撈針還難.

方法宣告

語法 : [存取修飾子] 返回值 方法名稱([參數1[, 參數2….]]){}, 如

public void setColor(Color c){}

方法若無返回值, 則為返回值需為 void, 若return_type有指定, 則程式碼一定要有 return 關鍵字

參數傳遞與返回值

呼叫端傳遞的值稱為引數(argument), 被呼叫的方法由參數(parameter)接收

在同類別中呼叫方法, 則可以直接呼叫,不需任何參考,也可以使用this.xxx()呼叫. 若是在不同的類別中呼叫, 則需視種類而定
static 方法 : 使用類別.方法
物件方法 : 使用物件.方法

class Pokemon{
    static int count=0;
    private float weight;
    public static int getCount(){return count;}
    public void setWeight(float weight){
        this.weight=weight;
    }
}
public class MethodTest {
    public static void main(String[] args) {
        System.out.println(Pokemon.getCount());
        Pokemon p1=new Pokemon();
        p1.setWeight(30.5f);
    }
}

如上述之程式碼中, static 方法, 直接使用Pokemon.getCount()即可
若是setWeight(), 因屬物件方法, 所以需先new 出一個物件, 再用物件去呼叫 p1.setWeight(30.5f);

變動的參數 — varargs

參數的個數可以為不確定, 但每個參數的型態都必需相同. 此為Java SE 5新提供的功能, 又稱為varargs(Variable arguments)

class Statistics{
    public float average(int... nums){
        int sum=0;
        for (int x:nums){
            sum+=x;
        }
        return ((float)sum/nums.length);
    }
}

特別注意的是, nums其實是一個陣列物件. 而且呼叫者也可以不傳入任何參數

… 稱為省略號, 只能出現在方法的最後一個參數
void calc(int x, int …y); 這是合法ok的
void calc(int …x, int y) : 這是錯誤的

方法的用途

可提高程式碼的可讀性高且易於維護, 加速開發及維護的速度, 並可重複使用, 並讓不同的物件相互溝通及分散執行工作

static 方法及變數

static 方法其實一直在使用, 比如想要隨機取得亂數, 就要使用Math.random, 想要計算2的10次方, 就要使用Math.pow(2,10);

Math.random()*26+97 : 隨機產生小寫a-z的字元

Math所有方法皆為static, 不需實例化Math類別即可呼叫裏面的方法. 此種方法又稱為類別方法.

static 變數僅存一份在類別之中,不會copy到每一個物件裏. 此種變數又稱為類別變數. 若加上final後,就會變成了常數. 加上final的常數, 必需立即初始化, 或者於建構子中要進行第一次初始化.

何時需宣告為static呢? 在獨立物件中執行時,與指定物件型態沒什麼重要的關係, 或者在實例化之前就必需存取此變數時, 就可以宣告為static.

在static 方法中, 不可以使用非static 方法及變數. 因為非static 方法及變數又稱為物件方法/物件變數, 是要new 出物件後, 才會出現的. 所以在static 方法中無法存取尚未存在的東西.

 方法重載(OverLoading)

試想如下狀況
int a=add(5, 10);
float b=add(5.5f, 2);
呼叫add時, 所傳入的參數型態不一樣, 那要如何定義add(?, ?)呢.

為了解決上述的問題, Java允許使用相同的方法名稱, 但需受限於一個條件 : 簽名不能一樣

什麼是簽名? 方法名+參數型態+參數個數, 叫作簽名. 簽名一樣, 則不可重載, 簽名不一樣, 重載才合法. 但特別注意一點, 方法的傳回值並不在簽名的範圍之內. 比如

public int  sum(int one, int two)
public int sum(int one, int two, int three) : ok
public float sum(float one, int two) : ok
public int sum(int x, int y) : error
public float sum(int one, int two) : error

Which method corresponds to the following method call?
pokemon.setInfo(2, 25.6f, "Pikachi");
A. public void setInfo(int level, float weight)
B. public void setInfo(level, float weight, name)
C. public void setInfo(float weight, String name, int level)
D. public void setInfo(int level, float weight, String name)

Answer : D

遞迴(Recursive)

在方法中自已呼叫自已, 稱為遞迴. 但其實並不是自已呼叫自已, 而是自已調用產生了一個跟自已一模一樣的全新方法.

public class Test {
    public static void main(String[] args) {
        int total=fac(5);
        System.out.printf("5*4*3*2*1= %d", total);
    }
    public static int fac(int x){
        if(x==1)return 1;
        else return x*fac(x-1);
    }
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *