Java 方法
本小節我們將學習什么是方法、如何自定義方法,并按照分類介紹每種方法的特點,對于有參數的方法傳值,會講到基本數據類型作為方法參數和引用數據類型作為方法參數的區別。也會學習可變參數方法的定義語法和使用場景,方法重載的使用和意義也是本節的重點學習內容。
1. 什么是方法
在前面我們已經了解過方法的概念,Java 程序的入口main()
就是一個方法。System.out.println();
語句中println()
也是一個方法。
如果你使用IntelliJ IDEA
查看代碼,可以使用Ctrl
+ 鼠標左鍵單擊代碼中的 println()
方法,查看 JDK 源碼中對于這個方法的定義:

上面的截圖就是我們經常調用的老朋友println()
方法的代碼實現,我們可以將方法理解為一個命名語句塊,通過其名稱 + 括號運算符()
可以調用。我們可以將需要重復編寫的代碼,封裝到一個方法中。提高代碼的復用性。
2. 如何定義方法
在 Java 中,定義一個方法的語法為:
訪問修飾符 返回類型 方法名(參數列表) {
若干語句;
return 方法返回值;
}
-
訪問修飾符有 4 種情況:
public
、private
、protected
,也可以省略(default
)。由于涉及到后面的面向對象相關知識,本節統一使用public
修飾方法; -
返回類型:可以是任何的數據類型或
void
,如果方法沒有返回值,返回類型設置為void
; -
方法名:方法名的命名規范和變量相同;
-
參數列表:參數是變量的一種類型,參數變量的作用域在方法內部;
-
方法體:方法內部的一些語句。當方法返回值為
void
時,可以省略return
語句。
3. 分類
根據方法是否帶有參數、是否有返回值,可以分為 4 類:
- 無參無返回值方法
- 無參帶返回值方法
- 帶參數無返回值方法
- 帶參數帶返回值方法
3.1 無參無返回值方法
無參無返回值方法,即參數列表為空,返回值為void
的方法。例如,我們經常需要輸出一段內容??梢詫⑤敵稣Z句封裝到方法中:
class MethodDemo1 {
// 定義無參無返回值方法
public void printText() {
// 三條輸出語句
System.out.println("你好新同學");
System.out.println("Java是就業前景最好的語言");
System.out.println("學Java就來慕課網");
}
}
上面代碼,在類MethodDemo1
中定義了一個方法printText
,其中有一些打印語句。那么如何調用這個方法,讓其執行呢?
對于非靜態方法(即非static
關鍵字修飾的方法),首先要使用new
關鍵字實例化類,生成一個對象,再通過對象名.方法名()
的方式去調動方法。
如下是 MethodDemo1 類方法調用的實例:
class MethodDemo1 {
// 定義無參無返回值方法
public void printText() {
// 三條輸出語句
System.out.println("你好新同學");
System.out.println("Java是就業前景最好的語言");
System.out.println("學Java就來慕課網");
}
public static void main(String[] args) {
// 實例化MethodDemo1類
MethodDemo1 methodDemo1 = new MethodDemo1();
// 調用printText方法
methodDemo1.printText();
}
}
運行結果:
你好新同學
Java是就業前景最好的語言
學Java就來慕課網
Tips:由于我們還沒有學習面向對象,此處對于對象的實例化,先記住這種固定寫法即可。本節的學習重點在于如何定義方法和調用方法。
運行結果:
你好新同學
Java是就業前景最好的語言
學Java就來慕課網
3.2 無參帶返回值方法
無參帶返回值方法,即參數列表為空,返回值不為void
的方法,方法體內部要使用return
語句返回其聲明的返回類型。
我們來自定義一個返回Hello World!
字符串的方法:
class MethodDemo2 {
// 定義無參帶返回值方法
public String getHelloStr() {
// 初始化變量str
String str = "Hello World";
// 返回str
return str;
}
public static void main(String[] args) {
// 實例化MethodDemo2
MethodDemo2 methodDemo2 = new MethodDemo2();
// 調用getStr方法,并且使用result變量接收返回值
String result = methodDemo2.getHelloStr();
// 打印返回值
System.out.println(result);
}
}
運行結果:
Hello World
3.3 帶參數無返回值方法
帶參數無返回值方法,即帶有參數列表,返回值為void
的方法。
參數列表可能有一個或多個參數,多個參數使用逗號(,
)隔開。定義方式為:DataType 參數名1, DataType 參數名2
,DateType 為參數的類型。
下面是一個根據長和寬求長方形面積的方法實例:
class MethodDemo3 {
// 定義帶參數無返回值方法
public void printArea(float a, float b) { // 此處的 a,b 為參數變量
float result = a * b;
System.out.println( "長方形面積為:" + result);
}
public static void main(String[] args) {
// 實例化MethodDemo3
MethodDemo3 methodDemo3 = new MethodDemo3();
// 初始化兩個變量
float width = 12.3f;
float height = 20f;
// 調用printArea方法,并將 width、height變量作為參數傳入
methodDemo3.printArea(width, height);
// 也可不提前初始化變量,直接傳入浮點型字面量作為參數。
methodDemo3.printArea(10.2f, 2.5f);
}
}
運行結果:
長方形面積為:246.0
長方形面積為:25.5
在調用帶參數方法時,有兩種傳參方式:
- 先初始化變量,再將變量傳遞給方法:
float a = 12.3f;
float b = 20f;
methodDemo3.printArea(a, b);
- 直接傳入對應類型字面量:
methodDemo3.printArea(10.2f, 2.5f);
當調用方把參數傳遞給方法時,調用時傳遞的值會按參數位置一一綁定,這也比較符合我們正常的思維邏輯。因此,對于有多個參數的方法,一定要注意每個參數的位置。
3.4 帶參數帶返回值方法
帶參帶返回值方法,即帶有參數列表,返回值不為void
的方法。
下面我們來看一個實例,求從1到n的平方和:
class MethodDemo4 {
// 定義帶參數帶返回值方法
public int getSumOfSquares(int n) {
int sum = 0;
for (int i = 1; i <=n; i++) {
// 求i的平方,并加和賦值給sum
sum += i * i;
}
// 返回計算結果
return sum;
}
public static void main(String[] args) {
// 實例化MethodDemo4
MethodDemo4 methodDemo4 = new MethodDemo4();
// 調用對象下getSumOfSquares方法,并用sumOfSquares變量接收返回結果
int sumOfSquares = methodDemo4.getSumOfSquares(5);
System.out.println("1到5的累加平方和為:" + sumOfSquares);
}
}
運行結果:
1到5的累加平方和為:55
我們也可以不定義變量接收返回結果,直接打印方法調用語句:
System.out.println("1到5的累加平方和為:" + methodDemo4.getSumOfSquares(5));
上面有參方法的例子,參數都是簡單的基本數據類型,當參數為數組時,我們再來看一個實例:
class MethodDemo5 {
/**
* 查找數組中元素是否包含指定元素
* @param arr 待查找數組
* @param element 所查找的元素
* @return boolean 查找結果,true包含; false不包含
*/
public boolean contains(int[] arr, int element) {
// 定義返回結果,默認為false,即未找到element元素
boolean result = false;
for (int value : arr) {
if (value == element) {
// 找到了element元素,將變量更新為true,并跳出循環
result = true;
break;
}
}
// 返回計算結果
return result;
}
public static void main(String[] args) {
// 實例化MethodDemo5
MethodDemo5 methodDemo5 = new MethodDemo5();
// 初始化一個數組
int[] intArray = {1, 3, 5, 6, 7, 9};
// 初始化待查找元素變量
int element = 10;
// 調用contains方法,并接收返回結果
boolean contains = methodDemo5.contains(intArray, element);
// 根據返回結果,輸出內容
if (contains) {
System.out.println("數組intArray中包含元素" + element);
} else {
System.out.println("數組intArray中不包含元素" + element);
}
}
}
運行結果:
數組intArray中不包含元素10
代碼解析:
上述代碼定義了一個查找數組中是否包含指定元素的方法,它將數組和指定元素作為方法參數,并且返回了一個布爾型的結果,方法體內部首先聲明了一個待返回的布爾變量,默認為false
,然后對數組參數進行迭代,只要找到與元素參數相同的元素,即更新返回變量為true
,跳出循環;如果數組迭代完成后依舊未找到指定的元素,那么待返回變量依然是false
,最后返回這個變量。在方法調用時,以一個布爾變量來接收結果,后續代碼根據這個布爾變量做了邏輯判斷,以執行不同的語句塊。
4. 方法傳值
調用方和方法之間有參數的傳遞時,要注意方法傳值問題。
4.1 基本類型的傳值
基本類型參數的傳遞,是調用方值的復制。雙方各自的后續修改,互不影響。簡單來講,方法內部對參數變量的任何操作,都不會影響到方法外部的變量。
我們看一個實例:
class Car {
public void speedUp(int speed) {
System.out.println("小汽車加速前,速度為:" + speed);
speed ++;
System.out.println("小汽車加速后,速度為:" + speed);
}
public static void main(String[] args) {
// 定義小汽車初始速度變量
int speed = 10;
// 實例化Car類,創建一個car對象
Car car = new Car();
// 調用car對象下的speed方法
car.speedUp(speed);
// 打印調用方法后速度參數的值
System.out.println("調用speedUp方法后,調用方的speed參數為:" + speed);
}
}
運行結果:
小汽車加速前,速度為:10
小汽車加速后,速度為:11
調用speedUp方法后,調用方的speed參數為:10
我們根據輸出的結果驗證了以上給出的結論。整型參數speed
是一個基本數據類型,在speedUp
方法內部進行了自增,但主方法中的speed
變量的值并不會受到其影響。
4.2 引用類型的傳值
引用類型參數的傳遞,調用方的變量,和接收方的參數變量,地址指向的是同一個對象。雙方任意一方對這個對象的修改,都會影響對方。
我們來看一個實例:
class NBATeam {
// 替換第一個球員方法
public void replaceFirstPlayer(String[] players, String playerName) {
// 替換第一個球員
System.out.println("將第一個球員替換:");
players[0] = playerName;
}
public static void main(String[] args) {
String[] players = {"詹姆斯", "科比", "杜蘭特", "喬丹"};
System.out.println("球隊中現有球員:");
for (String player : players) {
System.out.print(player + "\t");
}
System.out.println();
// 創建team對象并調用其替換球員方法
NBATeam team = new NBATeam();
team.replaceFirstPlayer(players, "皮蓬");
System.out.println("替換后球員:");
for (String player : players) {
System.out.print(player + "\t");
}
}
}
運行結果:
球隊中現有球員:
詹姆斯 科比 杜蘭特 喬丹
將第一個球員替換:
替換后球員:
皮蓬 科比 杜蘭特 喬丹
由運行結果可見:方法replaceFirstPlayer
的參數players
是數組類型,也就是引用類型。當我們在方法內部對players
進行操作,其方法外部(即主方法中)的players
變量也受到了影響。不只是數組,對象也是引用類型,其參數傳遞同樣遵循以上結論。我們在日常的編碼中,請注意區分基本類型和引用類型的方法傳值區別。
5. 可變參數
null我們可以使用可變參數列表聲明方法的參數??勺儏盗斜淼恼Z法:
參數類型... 參數名
我們可以結合可變參數來實現一個求和方法sum
,請閱讀下面實例:
class VariableParameter {
public void sum(int... n) {
int sum = 0;
// 可以對可變參數進行迭代
for (int i: n) {
sum = sum + i;
}
System.out.println("sum=" + sum);
}
public static void main(String[] args) {
// 創建對象
VariableParameter variableParameter = new VariableParameter();
// 調用方法,傳遞一個參數
variableParameter.sum(1);
// 調用方法,傳遞兩個參數
variableParameter.sum(2, 3);
// 調用方法,傳遞三個參數
variableParameter.sum(5, 6, 7);
}
}
運行結果:
sum=1
sum=5
sum=18
上述實例中,在主方法中給sum
方法傳參時,可選擇一個或多個參數傳遞。方法體內對可變參數n
進行迭代,也可以將可變參數n
改為數組:int[] n
,得到的效果是相同的。
當方法的參數列表有兩個或兩個以上參數時,可變參數一定要放在最后,請查看如下實例:
public void search(int element, int... elements) {
boolean existed = false;
for (int e: elements) {
if (e == element) {
existed = true;
break;
}
}
if (existed) {
System.out.println("找到元素:" + element);
} else {
System.out.println("未找到元素:" + element);
}
}
另外,也可以將數組傳遞給可變參數列表,例如,在主方法中調用上面的search
方法:
public class VariableParameter1 {
public void search(int element, int... elements) {
boolean existed = false;
for (int e: elements) {
if (e == element) {
existed = true;
break;
}
}
if (existed) {
System.out.println("找到元素:" + element);
} else {
System.out.println("未找到元素:" + element);
}
}
public static void main(String[] args) {
// 創建對象
VariableParameter1 obj = new VariableParameter1();
// 調用方法
obj.search(2, 1,2,3,4);
// 定義數組參數
int[] arr = {1,2,3,4};
// 將數組傳遞給可變參數列表
obj.search(2, arr);
}
}
運行結果:
找到元素:2
找到元素:2
上述兩種傳參方式都是合法的。
6. 方法重載
方法重載是指在一個類中定義多個同名的方法,但要求每個方法具有不同的參數的類型或參數的個數。調用重載方法時,Java 編譯器能通過檢查調用的方法的參數類型和個數選擇一個恰當的方法。方法重載通常用于創建完成一組任務相似但參數的類型或參數的個數或參數的順序不同的方法。
6.1 自定義方法的重載
例如,在Student
類中,有多個study
方法:
public class Student {
public void study() {
System.out.println("同學真好學!");
}
public void study(String name) {
System.out.println(name + "同學真好學!");
}
public void study(String name, int age) {
System.out.println(name + "同學真好學!" + "他今年" + age + "歲了");
}
public static void main(String[] args) {
// 實例化學生對象
Student student = new Student();
// 調用無參數方法
student.study();
// 調用單參數方法
student.study("Colorful");
// 調用雙參數方法
student.study("小慕", 20);
}
}
運行結果:
同學真好學!
Colorful同學真好學!
小慕同學真好學!他今年20歲了
代碼中的三個study
都是重載方法。通常來說,方法重載的返回值類型都是相同的。
如果我們在Student
類中再增加一個方法:
public String study() {
return "學習Java語言";
}
注意,上述的方法不是重載方法,因為我們已經在Student
類中定義了無參方法study
。
判斷一個方法是否是重載方法的原則:方法名相同,參數類型或參數個數不同。
6.2 JDK 中的方法重載
Java
語言本身的類也定義了很多方法重載的例子,例如String
類的substring
方法,用于字符串截?。?/p>
-
public String substring(int beginIndex); // 截取并返回從beginIndex位置到結束位置的字符串
-
public String substring(int beginIndex. int endIndex); // 截取并返回從beginIndex位置到endIndex-1位置的字符串
如下為實際應用的實例:
String hello = "Hello, Imooc";
String substring1 = hello.substring(7);
String substring2 = hello.substring(0, 5);
System.out.println(substring1);
System.out.println(substring2);
運行結果:
Imooc
Hello
7. 小結
本小節我們學習了 Java 方法,內容較多,我們一起來回顧一下所學的內容:
理解方法是一個命名語句塊很重要。方法提高了代碼的復用性,優質的方法提供者(如 JDK 中的方法),提高了調用者的開發效率。
定義方法時,要理解返回類型、方法名、參數列表和方法體的概念。通過方法的名稱 + 括號運算符()
可以調用該方法。
方法內部遇到return
時返回,返回類型為void
表示不返回任何值。
對于方法傳值問題,基本數據類型傳值:方法中對參數的修改,不會影響到方法調用方傳遞的變量值;引用數據類型傳值:方法中對參數的修改,會影響到方法調用方傳遞的對象。
可變參數通常用于參數數量是不確定的、可變化的方法。方法重載提高了程序的兼容性和易用性,為方法提供了多種可能性。