在上一篇的blog中,咱們知道了方法是類中的一個組成部分,是類或對象的行爲特徵的抽象。html
不管是從語法和功能上來看,方法都有點相似與函數。可是,方法與傳統的函數仍是有着不一樣之處:java
在結構化編程語言裏,函數是基本的程序組成單元,一個程序由一個個函數組成;編程
在面向對象編程語言裏,類纔是程序的基本單元,方法是屬於類或對象的,不能獨立存在;數組
Java語言裏方法的特徵主要在如下幾個方面:編程語言
方法不可以獨立的存在,方法只可以定義在類裏面,所屬與某個類或對象;函數
方法不可以被獨立地執行,必須使用類或者對象做爲調用者;ui
方法的分類,在Java中,方法主要分爲如下幾類:spa
Java中的方法,主要能夠分爲構造方法和普通方法,而普通方法能夠分爲類方法和對象方法;.net
在前面一篇blog,咱們已經知道了方法的定義方式,咱們再來回顧一下:htm
構造方法:
[修飾符] 類名([形參 參數名]){ //功能代碼 }
構造方法是你一種特殊的方法,它與普通方法有兩個不一樣之處:方法的名字必須和類名相同,它沒有返回值
普通方法:
[修飾符] 返回值 方法名([形參 參數名]){ //功能代碼 }
咱們能夠看到,普通方法的結構主要分爲5個部分,
修飾符:設置方法的訪問權限,能夠是public、protected、private、或者是不填;
返回值:調用該方法完成以後返回的內容,能夠是基本的數據類型,能夠是引用類型,也能夠沒有返回值,當沒有返回值時,使用void
方法名:自定義的標識符,主要是調用時使用,在類外部或非子類中調用時使用 類.方法名 或者 對象名.方法名
形參:形參調用該方法時所須要傳遞的參數,能夠有0個或多個
方法體{}:方法體內主要用於定義實現功能的代碼
看一個完整的例子:
定義一個Person類:
public class Person{ //定義一個Person類 public String name; //String類型的屬性name public int age; //int類型的屬性age public Person(String n, int a){ //構造方法,有兩個參數n和a,在建立對象是若是調用了該構造方法就會將name屬性設置爲傳進來的n,age爲a。 name = n; age = a; } public void showName(){ //普通方法,主要功能是顯示對象的name System.out.println("個人名字是" + name); } public void setAge(int a){ //普通方法,主要功能是設置對象的age,有一個參數,將對象的age設置爲傳遞進來的a變量 age = a; } public int getAge(){ //普通方法,有一個返回值,返回對象的age return age; } }
使用:
public class Test{ public static void main(String[] args){ Person p = new Person("張三", 20); //實例化一個對象,調用構造方法,傳遞進去兩個參數,將參數設置給了對象的name屬性和age屬性 p.showName(); //調用p對象的showName方法,執行了方法體裏面的代碼,打印出了p對象的name p.setAge(25); //調用了p對象的setAge方法,從新設置了p對象的age屬性值爲25 int pAge = p.getAge(); //調用了p對象的getAge方法,該方法有一個返回值,將p對象的age屬性值返回了出來,並將返回值賦值給了pAge變量 } }
不在關鍵點上追根問底的程序猿不是一個好廚師,下面咱們開看看方法的調用與參數傳遞在程序運行的內存中是一個什麼樣子滴狀況:
對於JVM運行機制,有興趣的能夠看看這幾篇文章:
固然,有興趣的而且有必定基礎的童鞋推薦你們看看一本好書《深刻理解Java虛擬機》
咱們來看看上面一個例子的代碼:
Person p = new Person("張三", 20);
建立對象的分析咱們在上篇blog中分析了,有興趣的能夠圍觀:[Java入門筆記] 面向對象編程基礎(一):類和對象 在最後面
對象建立完畢後,在內存中是這樣的一個樣子:
程序繼續向下執行:
p.showName();
調用p對象的showName方法,執行裏面的代碼:
println也是一個方法,這個是JavaApi中定義的方法,執行在內存中有點麻煩,如今先不看這個,執行完這句話後打印出「個人名字是張三」
繼續下下執行
p.setAge(25);
調用p對象的setAge方法
執行到這一步咱們發現,這個方法有一個int類型的形參,名字爲a,值爲25
繼續執行setAge方法,將a的值賦值給age
此時p對象的age屬性值變化爲爲25,方法執行完成後清除完成代碼的引用,繼續下面的代碼
int pAge = p.getAge();
執行到這一句會將p對象的age返回,而且賦值給int類型變量pAge,因此pAge的值此時也爲25:
方法重載是指在一個類中定義多個同名的方法,但要求每一個方法具備不一樣的參數的類型或參數的個數。調用重載方法時,Java編譯器能經過檢查調用的方法的參數類型和個數選擇一個恰當的方法。方法重載一般用於建立完成一組任務類似但參數的類型或參數的個數不一樣的方法。
方法的重載要求兩同一不一樣,三不受影響,兩同指的是同一個類中相同的方法名,一不一樣是方法的形參不一樣,這個不一樣主要體如今參數個數不一樣或者類型不一樣、參數位置不一樣。
兩不受影響是:
修飾符不一樣不影響方法重載。
方法的返回值類型不能用於區分方法的重載,也就是說,不管返回值相同或者不一樣,都對判斷方法是否重載沒有影響。
形參的名字不能用於區分方法是否重載,也就是說,若是形參的類型和個數都相同,只有參數的名字不一樣,則不構成重載。
構造方法的重載:
構造方法也是一種方法類型,也能夠實現重載,也遵循上面的規定。
例:
public class Person{ public String name; public int age; public Person(){} public Person(String n, int a){ name = n; age = a } public void setInfo(){ name = "張三"; age = 20; } public void setInfo(String n){ name = n; } public void setInfo(int a){ age = a; } public void setInfo(String n, int a){ name = n; age = a; } public void setInfo(int a, String n){ name = n; age = a; } }
上面的2個構造方法和4個setInfo都是重載的方法,由於它們知足了重載的要求:相同的類中相同的方法名,不一樣的參數類型或個數。
若是在上面的例子中添加下面的方法,不是重載:
private int setInfo(){} //修飾符和返回值不一樣,可是上面已經有一個沒有參數的setInfo方法,因此不是重載
public void set(){} //方法名不一樣,不是重載
public void setInfo(int b){} //參數名不一樣,類型上面有相同的,不是重載
重載方法的使用:
public class Test{ public static void main(String[] args){ Person p1 = new Person(); Person p2 = new Person("李四", 30); //這兩個對象被實例化時第一個沒有傳遞參數,因此調用第一個構造方法,第二個有兩個參數,因此調用第二個構造方法 p1.setInfo(); //沒有參數,調用第一個setInfo方法 p1.setInfo("王五"); //有一個String類型的參數,調用第二個setInfo方法 } }
若是咱們在實現某個方法不肯定方法有多少個參數數,咱們應該怎麼定義這個方法?
好比,若是咱們要寫一個實現加法的方法,而咱們不只僅是要實現2個數相加,而是不管是有多少個數,咱們都須要將它們加起來,咱們應該怎樣定義這個方法?顯然,用普通的形式定義或者重載都不能很好的實現,而咱們可使用jdk1.5以後增長的一種形參傳遞方法定義這個方法。
例:
public class Operation{ public static int add(int... num){ int result = 0; for(int i = 0; i < num.length; i++){ result += num[i]; } return result; } }
這個例子中咱們能夠看到,定義一個可變的形參的方法,只須要在類型後面加三個點便可,調用這個方法時既可傳遞多個相同類型的是參數。
在使用num參數時咱們能夠明顯的看到,就是用數組的形式在使用,所以這個可變的參數在本質上來講其實就是一個數組,不過在調用時能夠比較方便,請看:
public class Test{ public static void main(String[] args){ Operation ope = new Operation(); ope.add(1,2); //計算1加2 ope.add(3,4,5); //計算3加4加5 } }
咱們在使用時不須要再建立一個數組對象。