JavaSE第05篇:Java基礎語法之陣列、方法
目錄
本篇我們將會學習Java基礎語法之陣列和方法。陣列,是一種基礎的資料結構,陣列可以讓我們通過一個變數管理一組資料;方法可以將一個功能封裝,在需要這個功能的地方,只需要呼叫方法即可,而不用再重複編寫冗餘的程式碼。接下來,我們將會詳細講解Java中的陣列、方法。
第一章:陣列
1.1-為什麼要學習陣列(瞭解)
需求:統計10個人每個人的薪資,並計算出10個人薪資的總和以及平均薪資?
此時,面臨這個需求,我們會怎麼做呢?
按照目前已經學過的知識,我們可能會這麼解決:
- 定義10個變數,存放10人的薪資
- 讓10個變數相加,計算總薪資
- 讓總薪資除以10,計算平均薪資
以上的解決方案,確實可以滿足我們的需求,程式碼如下:
package com.penglei666.com; public class Test01 { public static void main(String[] args) { /* * 定義10個變數,存放10個人的薪資 * */ double salary1 = 10000; double salary2 = 13000; double salary3 = 15888; double salary4 = 12000; double salary5 = 11888; double salary6 = 15888; double salary7 = 10000; double salary8 = 13000; double salary9 = 12000; double salary10 = 11888; // 計算總薪資 double sum = salary1 + salary2 + salary3 + salary4 + salary5 + salary6 + salary7 + salary8 + salary9 + salary10; // 計算平均薪資 double avg = sum / 10; System.out.println("總薪資:" + sum); System.out.println("平均薪資:" + avg); } }
但是我們可以發現,一些不好的現象:
- 變數定義太多,若是計算100個人的薪資,那豈不是要定義100個變數,那1000個人、10000個人更不用說了。
- 連續累加,計算重複。
以上這些不好的問題,根本的原因,就是變數定義太多,一個具體的薪資資料對應一個變數,導致操作複雜且臃腫。
如何解決以上的問題呢?我們當然要從根本上解決,想辦法實現,讓一個變數管理一組資料。
此時,我們就需要學習陣列。
1.2-什麼是陣列 (理解)
一個固定長度的資料容器,可以有序地存放同類型的資料。
- 固定長度,存放資料的個數。
- 有序,容器中的每一個數據都有一個索引(編號),從左向右,索引從0開始。
- 同類型的資料,容器中的存放的資料型別要一致。
1.3-陣列的定義格式(記憶)
格式1:
資料型別[] 陣列名
double[]salay;
int[]age;
char[]arr;
格式2:
資料型別 陣列名[]
double salay[];
int age[];
char arr[];
以上僅僅是定義了陣列的名稱,但是未賦值。
1.4-陣列的動態初始化(記憶)
什麼是動態初始化
陣列動態初始化就是只給定陣列的長度,由系統給出預設初始化值
- double型別陣列,預設值0.0
- int型別陣列,預設值是0
- boolean型別陣列,預設值是false
- char型別陣列,預設值是0.0
- 物件型別陣列,預設值是null
動態初始化格式:
資料型別[] 陣列名 = new 資料型別[陣列長度];
資料型別 陣列名[] = new 資料型別[陣列長度];
double[]salary = new double[10];
=
左邊:
- double,表示陣列的型別
- [],表示是一個數組
- salary,表示陣列的名稱(變數名)
=
右邊:
-
new,為陣列開闢記憶體空間
-
double,表示陣列的型別
-
[],表示是一個數組
-
10,表示陣列的長度
1.5-訪問陣列元素(記憶)
訪問陣列元素(陣列中的資料),就是獲取陣列中的某一個位置的資料。
索引
每一個儲存到陣列的元素,都會自動的擁有一個編號,從0開始,向後逐一加1。
這個自動編號稱為陣列索引(index),可以通過陣列的索引訪問到陣列中的元素。
訪問陣列元素格式
陣列名[索引]
package com.penglei666.com;
public class Test02 {
public static void main(String[] args) {
double[]salary = new double[10];
// 輸出陣列,輸出結果:[D@b684286
System.out.println(salary);
// 輸出陣列中索引為0的元素,double陣列中資料預設值是0.0
System.out.println(salary[0]);
System.out.println(salary[0]);
System.out.println(salary[0]);
}
}
1.6-記憶體分配 (理解)
記憶體
-
記憶體是計算機中的重要原件,臨時儲存區域,作用是執行程式。
-
我們編寫的程式是存放在硬碟中的,在硬碟中的程式是不會執行的。
-
必須放進記憶體中才能執行,執行完畢後會清空記憶體。
-
Java虛擬機器要執行程式,必須要對記憶體進行空間的分配和管理。
Java中的記憶體分配
目前我們只需要記住兩個記憶體,分別是:棧記憶體和堆記憶體。
陣列在記憶體中的分配過程
public static void main(String[] args) {
double[]salary = new double[10];
// 輸出陣列,輸出結果:[D@b684286
System.out.println(salary);
// 輸出陣列中索引為0的元素,double陣列中資料預設值是0.0
System.out.println(salary[0]);
System.out.println(salary[1]);
System.out.println(salary[2]);
}
執行過程:
-
① 程式執行時,首先main方法,入棧執行。
-
② main方法執行時,發現new關鍵字建立陣列,則會在堆記憶體中,為陣列開闢連續的空間,並設定預設值。
-
③ 陣列開闢空間後,返回記憶體地址給陣列名稱,輸出陣列名稱,則輸出了記憶體地址。
-
④ salary[0]表示,通過陣列記憶體地址,找到記憶體堆區中陣列空間中的索引為0的資料。
-
⑤ salary[1]表示,通過陣列記憶體地址,找到記憶體堆區中陣列空間中的索引為1的資料。
-
⑥ salary[2]表示,通過陣列記憶體地址,找到記憶體堆區中陣列空間中的索引為2的資料。
1.7-基本型別和引用型別的區別(理解)
基本資料型別和引用資料型別
基本資料型別,之前學習的資料型別,如:int、long、double、boolean等。
引用資料型別,現在學習的陣列
就是引用資料型別
區別1:程式執行時,在記憶體中建立資料時,記憶體分配不同
- 基本資料型別:
- 會在棧記憶體開闢一塊空間存放資料。
- 引用資料型別:
- 會在堆記憶體開闢一塊空間存放資料具體資訊。
- 同時也會在棧記憶體開闢一塊空間存放堆資料的引用(堆區的地址)
區別2:資料傳遞過程不同
- 基本資料型別是值傳遞(資料在棧中會克隆一份新的,兩個資料互不影響)。
- 引用資料型別是引用傳遞(資料的引用在棧中會克隆一份新的,但兩個引用指向堆區中的同一個具體資料)
package com.penglei666.com;
public class Test02 {
public static void main(String[] args) {
/*【基本數型別值傳遞】*/
// 建立變數a,賦值為10
int a = 10;
// 把變數a,賦值給變數b
int b = a;
// 更改變數b的值
b = 20;
// 變數b發生改變,結果:20
System.out.println(b);
// 變數a沒有發生改變,結果:10
System.out.println(a);
/*【引用型別引用傳遞】*/
// 建立陣列arr1
int[]arr1 = new int[2];
// 建立陣列arr2,並把arr1賦值給arr2
int[]arr2 = arr1;
// 輸出arr1索引為0的值,結果為0
System.out.println(arr1[0]);
// 輸出arr2索引為0的值,結果為0
System.out.println(arr2[0]);
// 更改arr1索引為0的值
arr1[0] = 99;
// 輸出arr1索引為0的值,結果為99
System.out.println(arr1[0]);
// 輸出arr2索引為0的值,結果為99
System.out.println(arr2[0]);
}
}
基本資料型別資料傳遞過程
引用資料型別資料傳遞過程
1.8-陣列靜態初始化(記憶)
什麼是靜態初始化
在建立陣列時,直接將元素確定
靜態初始化格式:
- 完整版格式:資料型別[] 陣列名 = new 資料型別[]{元素1,元素2,...};
- 簡化版格式:資料型別[] 陣列名 = {元素1,元素2,...};
public class ArrayDemo {
public static void main(String[] args) {
//定義陣列
int[] arr = {1, 2, 3};
//輸出陣列名
System.out.println(arr);
//輸出陣列中的元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
1.9-陣列中常見的問題(瞭解)
問題1:索引越界異常
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[3]); // 異常
}
}
陣列長度為3,索引範圍是0~2,但是我們卻訪問了一個3的索引。
程式執行後,將會丟擲ArrayIndexOutOfBoundsException 陣列越界異常。在開發中,陣列的越界異常是不能出現的,一旦出現了,就必須要修改我們編寫的程式碼。
解決方式:將錯誤的索引修改為正確的索引範圍即可!
問題2:空指標異常
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
//把null賦值給陣列,變數將不會執行任何有效物件。
arr = null;
System.out.println(arr[0]);
}
}
arr = null 這行程式碼,意味著變數arr將不會在儲存陣列的記憶體地址,也就不允許再運算元組了,因此執行的時候會丟擲 NullPointerException 空指標異常。
解決方式:給陣列一個真正的堆記憶體空間引用即可!
1.10-陣列遍歷(重點)
陣列遍歷:就是將陣列中的每個元素分別獲取出來,就是遍歷。遍歷也是陣列操作中的基石。
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
}
以上程式碼是可以將陣列中每個元素全部遍歷出來,但是如果陣列元素非常多,這種寫法肯定不行,因此我們需要改造成迴圈的寫法。陣列的索引是 0 到 length-1 ,可以作為迴圈的條件出現。
- 獲取陣列的長度:陣列名.length
public class ArrayTest01 {
public static void main(String[] args) {
//定義陣列
int[] arr = {11, 22, 33, 44, 55};
//使用通用的遍歷格式
for(int x=0; x<arr.length; x++) {
System.out.println(arr[x]);
}
}
}
1.12-陣列應用(重點)
需求:統計10個人的薪資,計算總薪資、平均薪資和最大薪資。
package com.penglei666.com;
public class Test03 {
public static void main(String[] args) {
// 建立陣列,並靜態初始化10個人的薪資
double[]salary={12000,10000,13000,15000,14000,18000,10000,13000,15000,14000};
// 建立變數sum,表示總薪資,初始化為0
double sum = 0;
// 建立變數avg,表示平均薪資,初始化為0
double avg = 0;
// 建立變數maxValue,表示最高薪資,初始化陣列索引0為最大值,最終誰是最大值,需要比較
double maxValue = salary[0];
// 迴圈遍歷每一個人的薪資
for(int i = 0; i < salary.length; i++) {
// 取出每一個人的薪資,累計到變數sum中
sum+=salary[i];
// 從索引1開始,和maxValue比較,比maxValue值大,就把誰賦值給maxValue
if(i>0) {
if(salary[i]>maxValue) {
maxValue = salary[i];
}
}
}
// 計算平均薪資
avg = sum / salary.length-1;
// 輸出總薪資
System.out.println("薪資總和:" + sum);
System.out.println("平均薪資:" + avg);
System.out.println("最大薪資:" + maxValue);
}
}
第二章:方法
2.1-為什麼要學習方法(理解)
需求
一個簡單的需求:有三個陣列如下:
int[]arrA = {22,11,44,33};
int[]arrB = {1,4,5,2,3};
int[]arrC = {20,33,29,18};
分別計算並輸出陣列中最大值。
分析
按照現學的知識,我們可能會這麼做:
- 計算陣列arrA中的最大值
- 定義一個變數如:maxA,表示最大值,初始化為arrA[0]
- 迴圈遍歷陣列arrA,取出每一個值與maxA比較,若遍歷的元素大於maxA,則把當前元素賦值給maxA
- 遍歷結束後,maxA的值就代表最大值。
- 計算陣列arrB中的最大值
- 思路同上
- 計算陣列arrC中的最大值
- 思路同上
package com.penglei666.com;
public class Test04 {
public static void main(String[] args) {
/*定義三個陣列*/
int[]arrA = {22,11,44,33};
int[]arrB = {1,4,5,2,3};
int[]arrC = {20,33,29,18};
/*求陣列arrA中的最大值*/
int maxA = arrA[0];
for(int i = 1; i < arrA.length; i++){
if(arrA[i]>maxA) {
maxA = arrA[i];
}
}
System.out.println("最大值:" + maxA);
/*求陣列arrB中的最大值*/
int maxB = arrB[0];
for(int i = 1; i < arrB.length; i++){
if(arrB[i]>maxB) {
maxB = arrB[i];
}
}
System.out.println("最大值:" + maxB);
/*求陣列arrC中的最大值*/
int maxC = arrC[0];
for(int i = 1; i < arrC.length; i++){
if(arrC[i]>maxC) {
maxC = arrC[i];
}
}
System.out.println("最大值:" + maxC);
}
}
問題及解決方案
以上解決方案確實可以實現功能。但是存在這樣的問題:
- 程式碼重複
此處的重複,是邏輯重複,若有更多的陣列需要計算,豈不是要寫更多一樣的邏輯程式碼,這樣程式碼會越來越臃腫且難以維護,若需求更變,要求最小值,豈不是要逐一修改。
那如何去解決呢?以上是邏輯重複,變化的僅僅是陣列,所以我們想辦法這樣解決問題:
- 把邏輯封裝一個模板。
- 向這個模板中傳入一個數組,就會得到一個最大值的結果,傳入一個數組,就會得到一個最大值的結果。
這個模板只需要定義一次,在需要的時候呼叫這個模板即可。
在程式設計中,確實提供了這樣的語法來實現把邏輯封裝成一個模組,這個語法機制就是方法
2.2-什麼是方法 (瞭解)
方法,在程式設計中也叫函式,也表示功能。
方法,可以將一段程式碼封裝在一個程式碼塊中,代表一個功能
注意:
- 方法必須先建立才可以使用,該過程成為方法定義
- 方法建立後並不是直接可以執行的,需要手動使用後,才執行,該過程成為方法呼叫
2.3-無引數方法定義和呼叫(記憶)
定義格式
public static void 方法名 ( ) {
// 方法體;
}
示例如下:
public class Test05 {
public static void main(String[] args) {
}
/**
* 定義一個求陣列中最大值的方法
*/
public static void getMax(){
int[]arr = {22,11,44,33};
int max = arr[0];
for(int i = 1; i < arr.length; i++){
if(arr[i]>max) {
max = arr[i];
}
}
System.out.println(max);
}
}
注意:方法定義不能巢狀,比如:不能再main方法中定義getMax。
呼叫方法
呼叫格式:方法名()
示例如下:
public class Test05 {
public static void main(String[] args) {
// 呼叫getMax方法
getMax();
}
/**
* 定義一個求陣列中最大值的方法
*/
public static void getMax(){
int[]arr = {22,11,44,33};
int max = arr[0];
for(int i = 1; i < arr.length; i++){
if(arr[i]>max) {
max = arr[i];
}
}
System.out.println(max);
}
}
為什麼在main方法中呼叫,因為main方法是程式執行的入口。
每個方法在被呼叫執行的時候,都會進入棧記憶體,並且擁有自己獨立的記憶體空間,方法內部程式碼呼叫完畢之後,會從棧記憶體中彈棧消失。
2.4-帶引數方法定義和呼叫(記憶)
定義格式
引數:由資料型別和變數名組成 , 資料型別 變數名
方法定義時,引數中的資料型別與變數名都不能缺少,缺少任意一個程式將報錯,多個引數之間用,
分割
public static void 方法名 (引數1) {
方法體;
}
public static void 方法名 (引數1, 引數2, 引數3...) {
方法體;
}
示例:
public static void isEvenNumber(int number){
...
}
public static void getMax(int num1, int num2){
...
}
案例改進:
public class Test05 {
public static void main(String[] args) {
}
/**
* 求一個數組中的最大值
* @param arr 表示一個數組
*/
public static void getMax(int[]arr){
int max = arr[0];
for(int i = 1; i < arr.length; i++){
if(arr[i]>max) {
max = arr[i];
}
}
System.out.println(max);
}
}
呼叫
方法名(引數);
方法名(引數1,引數2);
方法呼叫時,要傳入實際的資料。
public class Test05 {
public static void main(String[] args) {
/*定義三個陣列*/
int[]arrA = {22,11,44,33};
int[]arrB = {1,4,5,2,3};
int[]arrC = {20,33,29,18};
/*求陣列arrA中的最大值*/
getMax(arrA);
/*求陣列arrB中的最大值*/
getMax(arrB);
/*求陣列arrC中的最大值*/
getMax(arrC);
}
/**
* 求一個數組中的最大值
* @param arr 表示一個數組
*/
public static void getMax(int[]arr){
int max = arr[0];
for(int i = 1; i < arr.length; i++){
if(arr[i]>max) {
max = arr[i];
}
}
System.out.println(max);
}
}
方法呼叫時,引數的數量與型別必須與方法定義中的設定相匹配,否則程式將報錯 。
2.5-形參和實參 (理解)
形參:在定義方法時,小括號中定義的變數。
實參:在方法呼叫時,小括號中傳入的實際的資料。
2.6-帶返回值方法的定義和呼叫(記憶)
需求:計算三個陣列中三個最大值的和。
此時,我們需要呼叫完方法後,得到結果,這個結果不是輸出,而是用來和其他最大值相加。
如何得到結果呢?
可以使用方法返回值,就是一個方法呼叫完畢後,可以通過一個變數接收方法的返回值。
帶返回值的方法定義:
public static 資料型別 方法名 ( 引數 ) {
return 資料 ;
}
方法定義時return後面的返回值與方法定義上的資料型別要匹配,否則程式將報錯。
範例:
// 檢測一個數字是否是偶數
public static boolean isEvenNumber( int number ) {
boolean isEven = number%2==0;
return isEven;
}
// 求兩個不同數字的最大值
public static int getMax( int a, int b ) {
if(a>b) {
return a;
}else {
return b;
}
}
呼叫
呼叫方式:返回值型別 變數名 = 方法名(實參)
示例:
public class Test06 {
public static void main(String[] args) {
// 檢測8是否是偶數
boolean isEven = isEvenNumber(8);
System.out.println(isEven); // isEven是true
// 求10和100哪個數字比較大
int max = getMax(10,100);
System.out.println(max); // max是100
}
/**
* 檢測要給數字是否是偶數
* @param number ,傳入一個數字
* @return 返回布林值,true表示是偶數,false表示不是偶數
*/
public static boolean isEvenNumber( int number ) {
boolean isEven = number%2==0;
return isEven;
}
/**
* 求兩個數字中的最大值
* @param a 一個數字
* @param b 另一個數字
* @return 返回較大的int型別數字
*/
public static int getMax( int a, int b ) {
if(a>b) {
return a;
}else {
return b;
}
}
}
案例程式碼:
public class Test05 {
public static void main(String[] args) {
/*定義三個陣列*/
int[]arrA = {22,11,44,33};
int[]arrB = {1,4,5,2,3};
int[]arrC = {20,33,29,18};
/*求陣列arrA中的最大值*/
int maxA = getMax(arrA);
/*求陣列arrB中的最大值*/
int maxB =getMax(arrB);
/*求陣列arrC中的最大值*/
int maxC = getMax(arrC);
// 求最大值的和
System.out.println(maxA + maxB + maxC); // 82
}
/**
* 求一個數組中的最大值
* @param arr 表示一個數組
* @return 返回一個int型別的數字,表示最大值
*/
public static int getMax(int[]arr){
int max = arr[0];
for(int i = 1; i < arr.length; i++){
if(arr[i]>max) {
max = arr[i];
}
}
return max;
}
}
2.7-方法注意事項(瞭解)
① 方法不能巢狀定義
public class MethodDemo {
public static void main(String[] args) {
}
public static void methodOne() {
public static void methodTwo() {
// 這裡會引發編譯錯誤!!!
}
}
}
② void表示無返回值,可以省略return,也可以單獨的書寫return,後面不加資料
public class MethodDemo {
public static void main(String[] args) {
}
public static void methodTwo() {
//return 100; 編譯錯誤,因為沒有具體返回值型別
return;
//System.out.println(100); return語句後面不能跟資料或程式碼
}
}
2.8-方法通用格式(記憶)
通用格式
public static 返回值型別 方法名(引數) {
方法體;
return 資料 ;
}
-
public static ,修飾符,目前先記住這個格式
-
返回值型別,方法操作完畢之後返回的資料的資料型別,如果方法操作完畢,沒有資料返回,這裡寫void,而且方法體中一般不寫return
-
方法名,呼叫方法時候使用的標識,定義規則和變數名一樣。
-
引數,由資料型別和變數名組成,多個引數之間用逗號隔開。
-
方法體,完成功能的程式碼塊
-
return,如果方法操作完畢,有資料返回,用於把資料返回給呼叫者
如何定義方法
- 明確返回值型別:主要是明確方法操作完畢之後是否有資料返回,如果沒有,寫void;如果有,寫對應的資料型別。
- 明確引數:主要是明確引數的型別和數量
如何呼叫方法
void型別的方法,直接呼叫即可。
非void型別的方法,推薦用變數接收呼叫。
2.9-方法的過載(理解)
在Java程式中,可以定義的多個·重名
的引數列表不同
(引數的個數或型別不同)的方法。這種現象叫做方法的過載。
public static void fn(int num1,int num2){
System.out.print(num1 + num2);
}
// 定義有參有返回值方法
public static int fn(int num1,int num2,int num3){
return num1 + num2 + num3;
}
注意:方法的過載與方法的返回值沒有關係
錯誤示例:以下不是方法過載,與返回值沒有關係。
public static int fn(int num1,int num2){
}
public static void fn(int num1,int num2){
}
第三章:IDEA 安裝下載教程
連結:https://pan.baidu.com/s/1fuZucWizXdLLfhBNu97Bbg
提取碼:bfbc