1. 程式人生 > 實用技巧 >JavaSE學習筆記(四)——Java中的方法

JavaSE學習筆記(四)——Java中的方法

一、Java中的方法

需求:求整數10和整數3的乘積,然後在求整數2000和整數300的乘積。

public class MethodTest01 {

public static void main(String[] args){

int i = 10;

int j = 3;

int k = i * j;

System.out.println("i * j = " + k);

int l = 2000;

int m = 300;

int n = l * m;

System.out.println("l * m =" + n);

}

}

功能已經實現,但是存在的問題是,兩段程式碼完成的功能相同,資料的型別也相同。只是具體的資料不同。並且程式碼重複使用了兩次,雖然實現了功能,但缺點是相同功能的程式碼不能實現重用。所以在

Java中可以使用方法來實現相同功能的程式碼塊重複利用。

1.1方法的定義

方法就是一段程式碼片段,可以完成特定的功能,並且可以重複利用。定義方法的語法格式如下。

[方法修飾列表] 返回值型別 方法名(方法形式引數列表){

方法體;

}

方法修飾符:可以是publicprotectedprivateabstractstaticfinalsynchronized。注意:其中publicprotectedprivate不能同時存在,只能是其中之一。

方法的返回值型別:可以是Java語言中的任何一種資料型別(基本資料型別和引用資料型別)。如果該方法執行結束之後,沒有任何返回值,那麼定義方法的時返回值型別為

void。如果存在返回值,使用 return語句。Return語句後面不能再執行語句,因為不可能會執行到,編譯不能通過。

方法名:合法的識別符號。

方法引數列表:定義方法時可以有引數,也可以沒有引數,如果有多個引數,引數之間要使用逗號進行分隔。

定義一個方法實現上面的需求。

public class MethodTest02 {

public static void main(String[] args){

// 呼叫static修飾的靜態方法需要使用類名.的方式

// 直接呼叫方法並傳入需要乘積的引數

MethodTest02.method(10, 3);

MethodTest02.method(2000, 300);

}

// static修飾的方法是靜態方法

public static void method(int i,int j){

int product = i * j;

System.out.println("i * j = " + product);

}

}

定義方法。

public class MethodTest03 {

public static void main(String[] args){

// 呼叫方法,靜態方法直接使用類名.的方式進行呼叫

MethodTest03.method01();

// 呼叫方法時同時傳遞引數給方法

MethodTest03.method02("張三");

// 呼叫有返回值的方法

int product = MethodTest03.method03(20, 30);

System.out.println("product = " + product);

}

// 定義方法

// public 公共的,外面的類可以呼叫

// static 方法是靜態的

// void 沒有返回值

// method01 方法名

// 方法沒有引數

public static void method01(){

System.out.println("Hello Java");

}

// 方法帶有一個String型別的引數

// 引數name是區域性變數,作用域在方法體內

public static void method02(String name){

System.out.println(name);

}

// 方法有兩個int型別的引數

// 方法有返回值,返回值型別為int型別

public static int method03(int i,int j){

int product = i * j;

// 方法有返回值,必須有return語句,並且返回值的型別與方法定義的型別

// 相同,否則編譯不能通過

return product;

// return 語句後面不能存在其他語句,否則編譯不能通過

// System.out.println("product = " + product);

}

}

1.2方法的呼叫

靜態方法的呼叫原則。在同一個類中,呼叫靜態方法可以使用類名.的方式進行呼叫,也可以直接使用方法名進行呼叫。

public class MethodTest04 {

public static void main(String[] args){

// 在同一個類中,可以直接使用方法名呼叫靜態方法

method02();

// 也可以使用類名的方式呼叫靜態方法

MethodTest04.method02();

// 不在同一個類中的靜態方法必須使用類名.的方式進價呼叫

A.method03();

}

public void method01(){

method02();

MethodTest04.method02();

}

public static void method02(){

System.out.println("Hello Java");

}

}

class A{

// A類中定義的靜態方法

public static void method03(){

System.out.println("A method03()");

}

}

呼叫帶引數的靜態方法,需要傳遞相應型別的引數。通常情況下呼叫有返回值的方法就是要取得返回值,返回值變數的型別必須與方法返回值的型別相同。在方法中,return語句執行則方法結束,執行流程放回到方法呼叫處。

public class MethodTest05 {

public static void main(String[] args){

// 呼叫有返回值的靜態方法

int success = method01(true);

// 返回值型別是方法的返回值型別

// 引數的型別必須是方法定義的引數型別,並且順序相同

int product = method02(10,3);

System.out.println("product: " + product);

// 不在同一個類中,必須採用類名.的方式呼叫靜態方法

A.method03("張三");

}

// 靜態方法

public static int method01(boolean b){

/*

if(b){

return 1;

}else{

return 0;

}

*/

if(b){

return 1;

}

return 0;

}

// 靜態方法,返回值型別是int型,兩個引數。形式引數型別是int

public static int method02(int i,int j){

// 返回值的型別必須是方法定義的返回值型別

return i / j;

// return語句執行,方法結束,所以不能有語句在return後面,編譯不能通過

// System.out.println(i / j);

}

}

class A{

// 定義的靜態方法

public static void method03(String name){

System.out.println("name: " + name);

}

}

如何終止方法的執行,採用的方式是如果符合某種條件,使用return語句終止方法的執行。

public class MethodTest06 {

public static void main(String[] args){

method01(11);

method01(8);

}

// 靜態方法,沒有返回值,一個形式引數,型別是int

public static void method01(int i){

// 如果引數值大於10終止方法執行

if(i > 10){

// return語句執行,方法結束

return;

}

for(;i <= 10;i++){

if(i == 5){

// break只是結束終止迴圈

break;

}

System.out.println("i = " + i);

}

System.out.println("break後要執行的語句");

}

}

return語句的使用方式。

public class MethodTest07 {

public static void main(String[] args){

// 靜態方法呼叫

method01();

String info = method02();

System.out.println(info);

}

public static void method01(){

// 方法沒有返回值,如果使用returnreturn後面不能存在語句

//return;

// 編譯可以通過,雖然最後的語句不會輸出

if(true){

return;

}

System.out.println("HelloWord");

}

public static String method02(){

// 如果方法有返回值,必須存在return語句,後面的值型別必須和返回型別

// 相同,並且return語句後面不能跟其他語句

//return "HelloWord";

// 這種方式可以,

/*

if(true){

return "HelloWord";

}else{

return "OK";

}

*/

// 這種方式可以

if(true){

return "HelloWord";

}

return "OK";

// 方法有返回值,return語句一定是最後一條語句,否則編譯不能通過

//System.out.println("HelloWord");

}

}

1.3方法的過載

需求:定義三個方法,分別是int型別、double型別和long型別實現乘積的方法,方法有返回值。

public class MethodTest08 {

public static void main(String[] args){

int product1 = productInt(10,20);

System.out.println(product1);

double product2 = productDouble(10.11,93.23);

System.out.println(product2);

long product3 = productLong(10L,20L);

System.out.println(product3);

// 注意:型別從小容量到大容量,自動型別轉換

productInt(10,20);

productDouble(10,20);

productLong(10,20);

}

public static int productInt(int i1,int i2){

return i1 * i2;

}

public static double productDouble(double d1,double d2){

return d1 * d2;

}

public static long productLong(long l1,long l2){

return l1 * l2;

}

}

上面的程式碼實現了功能,但是存在的問題是每個方法的方法名稱不同,相同的是求兩個數值型別的值的乘積。另外,還需要記憶多個方法名,並且程式碼不是特別易讀。如果方法實現的功能相同,只是引數型別或者引數的數量不同,可以採用方法過載的方式,如下例子。

public class MethodTest09 {

public static void main(String[] args){

int product1 = product(10,20);

System.out.println(product1);

double product2 = product(10.11,93.23);

System.out.println(product2);

long product3 = product(10L,20L);

System.out.println(product3);

}

public static int product(int i1,int i2){

return i1 * i2;

}

public static double product(double d1,double d2){

return d1 * d2;

}

public static long product(long l1,long l2){

return l1 * l2;

}

}

修改後,三個方法的方法名稱相同,引數型別不同,返回值型別不同,但是呼叫時只需要傳入不同型別的引數,不需要指定呼叫哪個方法,系統會根據引數的型別自動呼叫相應的方法並將結果返回。並且不需要記憶更多的方法名稱。

方法過載的條件。

1.方法過載只出現在同一個類中

2.方法名相同

3.方法的引數型別,個數,順序至少有一個不同

4.方法的返回型別可以不同(不依靠返回型別來區分過載)

5.方法的修飾符可以不同,因為方法過載和修飾符沒有任何關係

public class MethodTest10 {

public static void main(String[] args){

}

// 方法過載必須在同一個類中

// 引數型別不同,是方法過載

public static void m1(int i1,int i2){}

public static void m1(double d1,double d2){}

// 引數數量不同,是方法過載

public static void m2(int i1){}

public static void m2(double d1,double d2){}

// 引數順序不同,是方法過載

public static void m3(int i1,double d1){}

public static void m3(double d1,int i1){}

// 引數型別相同,引數個數相同,不是方法過載,是方法重複

//public static void m4(int a){}

//public static void m4(int b){}

// 引數型別和個數相同,返回值型別不同,不是方法過載,

// 方法過載和返回值型別無關

//public static int m5(int i){}

//public static void m5(int i){}

// 引數相同,訪問修飾符不同,不是方法過載,方法過載和訪問修飾符無關

//private static void m6(){}

//public static void m6(){}

}

方法過載舉例。

public class MethodTest11 {

public static void main(String[] args){

// sun提供的方法過載例子

System.out.println(10);

System.out.println(23.2);

System.out.println(true);

System.out.println('A');

}

}

1.4類、方法、屬性(靜態變數)的關係

在一個類中,從類和成員的角度可分為靜態的和成員的部分。靜態的部分可分為靜態變數、靜態方法和靜態內部類等等。成員的部分可以分為成員變數、成員方法和成員內部類等等。注意:也就是說,在類體中只存在兩部分內容,一是屬性(成員的或靜態的),二是方法(成員方法或靜態方法)或內部類。那麼可以執行的程式碼只能存在與方法中,包括成員方法或靜態方法,所以,存在與方法中的程式碼是為了實現一個特定的功能,就像一個工廠生產特定的產品,方法的引數類似於工廠需要的生成原料,而方法的返回值相當於工廠生產出的產品。

public class MethodTest12 {

// 類體

// 成員屬性

int i = 10;

// 靜態變數

static String country = "中國";

// 成員方法

public void method01(int i){

// 方法體

// 可以執行的程式碼

// 將引數做一些特殊的處理

System.out.println(i);

}

// 靜態方法

public static int method02(int i1,int i2){

// 方法體

// 可以執行的程式碼

// 實現特定功能,並返回特定的結果

return i1 + i2;

}

public static void main(String[] args){

// 方法體

// 可以執行的程式碼

// 程式的執行入口方法

}

}

1.5呼叫方法的執行流程

1.5.1棧的概念

當通過Java命令執行一個程式時,會啟動一個JVMJava虛擬機器程序,並建立程式執行環境,會建立程式執行的棧記憶體,下面的圖做了簡單的說明。

wKiom1f6KROzvpUBAAAXSQm5JTs396.png-wh_50


1.1.1程式的執行過程

下面通過一個程式說明程式的執行過程。

public class MethodTest13 {

public static void main(String[] args){

// 呼叫method01()方法

method01(10);

}

// method01()方法呼叫method02()方法

public static void method01(int i){

method02(i);

}

// method02()方法呼叫method03()方法

public static void method02(int i){

method03(i);

}

public static void method03(int i){

System.out.println("i: " + i);

}

// method04()方法沒有被呼叫

public static void method04(int i){

System.out.println(i);

}

}

main()方法呼叫method01()方法,method01()方法呼叫method02()方法,method02()方法呼叫method03()方法,在method03()方法中將引數輸出。下面通過一個圖說明程式的執行流程。

注意:當方法被呼叫時,才會在記憶體中為方法分配空間。如果只是定義了方法,但是沒有被呼叫,不會為方法在記憶體中分配空間。方法被呼叫時,Java虛擬機器會為方法在棧記憶體中為方法分配空間。方法被呼叫時會發生壓棧操作,當方法執行結束後會發生彈棧操作。

一、 遞迴

方法的遞迴呼叫就是方法自身呼叫自身。通常在樹形結構訪問時用到,如:目錄的遞迴檢索,又如許可權管理中許可權目錄數的訪問等等。下面的例子是遞迴的簡單演示。

public class RecursionTest01 {

public static void main(String[] args){

// 呼叫method01()方法

method01(10);

}

// 方法method01()

public static void method01(int i){

// 方法自己呼叫自己,無限呼叫下去沒有返回

method01(i);

}

}

在上面的例子中,因為遞迴沒有結束的條件,所以每呼叫一次method01()方法,就會在記憶體中開闢空間,產生壓棧操作,但沒有出棧操作,不會釋放記憶體,會導致棧記憶體溢位錯誤!所以遞迴程式必須要有結束條件。

不使用遞迴計算1~n整數的和。

public class RecursionTest02 {

public static void main(String[] args){

int sum = method01(10);

System.out.println(sum);

}

public static int method01(int n){

int sum = 0;

for(int i = 1;i <= n;i++){

sum += i;

}

return sum;

}

}

使用遞迴實現1~n的求和。

public class RecursionTest03 {

public static void main(String[] args){

int sum = sum(5);

System.out.println(sum);

}

public static int sum(int n){

// 如果引數n等於1,直接返回

if(n == 1){

return 1;

}else{

// 否則,將引數n減一作為引數呼叫自身,返回的值與引數n的和就是

// 最終的結果。

return n + sum(n - 1);

}

}

}

上面程式的執行流程:

wKioL1f6KbezubBhAAA24viyv7k521.png



練習:

1.採用遞迴的方式求1~n的偶數的和。

public class RecursionTest04 {

public static void main(String[] args){

int sum = sum(5);

System.out.println(sum);

}

public static int sum(int n){

if(n % 2 != 0){

n -= 1;

}

if(n == 2){

return 2;

}else{

return n + sum(n - 2);

}

}

}

2.採用遞迴的方式求n!

public class RecursionTest05 {

public static void main(String[] args){

int sum = product(5);

System.out.println(sum);

}

public static int product(int n){

if(n == 1){

return 1;

}else{

return n * product(n - 1);

}

}

}

3.不採用遞迴的方式實現n!。

public class RecursionTest06 {

public static void main(String[] args){

int sum = product(5);

System.out.println(sum);

}

public static int product(int n){

int product = 1;

for(int i = 1;i <= n;i++){

product *= i;

}

return product;

}

}


轉載於:https://blog.51cto.com/dongkevin/1859921