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

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