2018年7月26日 星期四

JAVA基礎必修課學習筆記 (1)

  因工作的緣故,閱讀蔡文龍、張志成編著的《JAVA SE 8基礎必修課》以學習Java程式基礎,目前最新的Java程式版本為Java SE 10,筆記中的程式撰寫習慣盡量仿照Python以增加可讀性。

一、Java概述

下載、安裝Java
l   JVM(Java Virtual Machine) + 開發技術、使用者介面工具箱、整合類別庫、基礎類別庫 = JRE(Java Runtime Environment)
JRE(Java Runtime Environment) + Java
語言、工具程式與API = JDK(Java Development Kit)
l   檢查電腦是否已安裝JDK(Java Development Kit),預設安裝於C:\Program Files\Java
jre
資料夾-如果只需執行Java程式,則只要安裝JRE即可
jdk
資料夾-如果需要開發Java程式,則必須下載安裝JDKhttp://www.oracle.com/technetwork/java/javase/downloads/index.html
l   環境變數設定,請至「編輯系統環境變數」,點選「環境變數」,再點選「系統變數」:
JDK
安裝路徑的設定:
 新增變數名稱-JAVA_HOME
 新增變數值-C:\Program Files\Java\jdk-10
.class
檔所在路徑的設定:
 新增變數名稱-CLASSPATH
 新增變數值-.
JAVA
編譯器和執行檔路徑的設定:
 點選變數名稱-Path
 新增變數值-C:\Program Files\Java\jdk-10\bin
在命令提示字元測試設定,查看Java版本:
 java -version
l   C:\Program Files\Java\jre資料夾:
一般執行環境Public JRE
l   C:\Program Files\Java\jdk資料夾:
bin
資料夾:
 javac.exe用以將.java檔編譯成.class檔。
 java.exe用以解譯.class檔。
 javap.exe用以將.class檔反組譯成.java檔。
 javadoc.exe用以產生Java API文件。
 appletviewer.exe用以執行Java Applet程式。
lib
資料夾:
 放置Java程式各種工具類別。

編寫、編譯、解譯、反組譯程式與產生Java API文件
l   編寫程式:
/**
C:\Java以記事本編寫存檔為Hello.java*/
// public
表示這個類別沒有存取限制
//
若用public宣告,檔案名稱(Hello.java)與類別名稱(class Hello)兩者要相同,英文的大小寫也要一致
public class Hello{
    // static
宣告main()為靜態方法,屬於整個類別所有
    // void
宣告main()結束的時候,不用傳回任何型別的值
    // main()
是應用程式開始執行的起點
    // String args[]
是傳給main()的引數
    public static void main(String args[]){
        System.out.println("Hello World");
    }
}
l   javac.exe編譯程式:
//
在命令提示字元輸入,將.java檔編譯成.class
javac C:\Java\Hello.java
//
查看引數說明
javac -help
l   java.exe解譯程式:
//
在命令提示字元輸入,解譯.class檔,注意檔案名稱不可以加.class
cd C:\Java
java Hello
//
查看引數說明
java -help
l   javap.exe反組譯程式:
//
在命令提示字元輸入,將.class檔反組譯成.java
cd C:\Java
javap Hello > Hello2.java
//
在命令提示字元輸入,將.class檔反組譯成.txt
// -c
指反組譯.class
// -p
指所有類別和成員
javap -c -p Hello > Hello2.txt
//
查看引數說明
javap -help
l   javadoc.exe將文件註解建立成Java API文件:
//
在命令提示字元輸入,將.java檔文件註解建立成Java API文件
// -d doc
指在目前工作目錄新增doc資料夾存放產生的Java API文件
// -private
指所有類別和成員
//
查看產生的Java API文件,index.html是文件的首頁
javadoc -d doc -private C:\Java\Hello.java
//
查看引數說明
javadoc -help

下載、使用Eclipse IDE for Java Developers
l   下載後免安裝,解壓縮至C:\eclipse即可:
http://www.eclipse.org/downloads/
l   點選C:\eclipse\eclipse.exe使用Eclipse IDE
Eclipse Launcher
Workspace設定在C:\Java
新增專案資料夾-File/New/Java Project
新增類別程式-File/New/Class
存檔-File/Save
執行程式-Run/Run
載入專案-File/Import

Java程式架構
l   專案資料夾:
例如在C:\JavatestProject資料夾。
l   類別程式:
例如testProject\src\testPackage\test.java,程式碼package testPackage;用以宣告test類別放在testPackage套件資料夾裡。
l   預載類別套件:
例如import java.util.*;*代表預載全部。
l   Class類別:
例如public class test,至少需一組類別,若用public宣告,檔案名稱(test.java)與類別名稱(class test)兩者要相同,英文的大小寫也要一致。
l   程式進入點(Entry Point)
main()
l   執行區塊(Block)
{}
區隔的範圍。
l   敘述(Statement)
例如Scanner obj = new Scanner(System.in);,陳述式是以;結尾的一行指令。
l   註解:
分為3種,其中「文件註解」是可用javadoc.exe產生Java API文件的註解格式-
//
單行註解
/*
多行註解*/
/**
文件註解*/
l   C:\Java\testProject\src\testPackage\test.java
package testPackage;
//
匯入java.util.Scanner類別,其後撰寫程式時僅寫Scanner即可
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        //
實作一個Scanner類別物件obj,可以接受輸入的字串
        Scanner obj = new Scanner(System.in);
        System.out.print("Please Input Your Name: ");
        //
宣告一個字串變數strName,存放scn.next()方法取得的字串
        String strName = obj.next();
        System.out.println("Hi! " + strName + ", Welcome to Java World!");
        obj.close();
    }
}

二、資料型別與運算子

識別字(Identifier)
l   變數、類別、物件的名稱為識別字,識別字只允許由大小寫字母(a-zA-Z)、數字(0-9)、底線(_)、錢字號($)構成,但識別字不能以數字開頭,也不能使用保留字(Reserved Word)

基本資料型別(Primitive Data Type)或常值(Literal)
l   文字:char單一字元(Unicode)
數值:byte整數、short整數、int整數、long整數、float浮點數、double浮點數
布林:boolean布林值
l   文字常值:
字元常值:必須用單引號('')括起來,例如'H'
字串常值:必須用雙引號("")括起來,例如"Hello World"
逃逸字元(Escape Character):必須用反斜線(\),例如\f代表游標移到下一頁、\b代表游標倒退一格、\r代表游標移到本行最前面。
l   數值常值:
整數常值:包含10進位制、2進位制(0b0B開頭)8進位制(0開頭)16進位制(0x0X開頭)
浮點常值(實數常值):包含25.0e-04(0.0025)1.25e-3(0.00125)25e+3(25000.0)等,Java SE7以後的版本提供底線(_)分隔常值,例如1_2345(12345)
l   布林常值:
必須是truefalse

變數宣告(Declare)
l   Java提供了2種主要存取資料方式:
直接存取資料的基本資料型別(Primitive Data Type)
間接存取資料的參考資料型別(Reference Data Type)
變數採基本資料型別宣告。
l   資料型別 變數名稱 = 初值, 變數名稱 = 初值;,例如:
char yesOrNo = 'y';
int year;
int month = 6, day;
double height = 178.8;
//
浮點數常值預設為double,必須使用F指定54.6float資料型別
float weight = 54.6F;
boolean ok = true;

基本資料型別(Primitive Data Type)轉換
l   自動型基本資料型別轉換:
條件一:資料型別必須是相容的,數值型別的整數與浮點數彼此相容,而數值型別、字元型別、布林型別彼此不相容。
條件二:轉換後的資料型別儲存範圍需大於轉換前的資料型別,例如int可以儲存byte的值,反之會發生錯誤。
l   強制型基本資料型別轉換(縮小轉換)
//
程式中的整數常值,編譯器會預設為int資料型別
long num = 2147483648L;
//
錯誤,因2147483648依舊為int資料型別
long num = (long)2147483648;
//
程式中的浮點常值,編譯器會預設為double資料型別
float pi = 3.14F;
float pi = (float)3.14;

基本資料型別(Primitive Data Type)與參考資料型別(Reference Data Type)
l   全域資料(Global)
使用static保留字宣告的資料成員變數都會存放在Global儲存空間,稱為靜態成員或類別成員。
l   堆疊(Stack)
宣告屬於基本資料型別的變數都會存放在Stack儲存空間。
l   堆積(Heap)
使用new保留字建立參考資料型別的物件實體時,物件實體參考值都會存放在Stack儲存空間,而物件實體本身都會存放在Heap儲存空間,例如陣列、類別、字串等都是屬於參考資料型別:
int[] x;
x = new int[] {1, 2, 3};
int[] y = x;
y[1] = 15;
System.out.print("x[1]: " + x[1] + " y[1]: " + y[1]);
à x[1]: 15 y[1]: 15

運算子
l   指定運算子(Assignment Operator)
就是'='符號。
l   算術運算子(Arithmetic Operator)
包含'+''-''*''/''%'(取餘數)符號。
l   遞增和遞減運算子(Increment & Decrement Operator)
包含'++''--'符號。
int a = 10, b;
//
後置式(Postfix),先指定給ba再加1
b = a++;
System.out.println("a = " + a + ", b = " + b);
à a = 11, b = 10
//
前置式(Prefix)a先加1,再指定給b
b = ++a;
System.out.println("a = " + a + ", b = " + b);
à a = 12, b = 12
b = a--;
System.out.println("a = " + a + ", b = " + b);
à a = 11, b = 12
b = --a;
System.out.println("a = " + a + ", b = " + b);
à a = 10, b = 10
l   關係運算子(Relational Operator)
包含'==''!=''>=''<=''>''<'符號。
l   布林邏輯運算子(Boolean Logical Operator)
包含'&'(AND)'&&'(Short-Circuit AND)'|'(OR)'||'(Short-Circuit OR)'^'(XOR)'!'(NOT)符號。
boolean a = true, b = false;
System.out.println(a & a);
à true
//
只要遇到false,馬上判斷false
System.out.println(a && b);
à false
System.out.println(a | a);
à true
//
只要遇到true,馬上判斷true
System.out.println(a || b);
à true
System.out.println(a ^ a);
à false
System.out.println(a ^ b);
à true
System.out.println(b ^ a);
à true
System.out.println(b ^ b);
à false
System.out.println(!a);
à false
System.out.println(!b);
à true

主控台輸出與輸入
l   System.outSystem.inSystem.err
System.out
為標準輸出資料串流,預設為主控台,一般指的是螢幕。
System.in
為標準輸入資料串流,預設為鍵盤。
System.err
為標準錯誤資料串流,預設為主控台,一般指的是螢幕。
l   輸出:
//
使用println()方法輸出資料後會換行
System.out.println("Hello World");
//
使用print()方法輸出資料後不會換行
System.out.print("Hello World");
// printf()
方法等於format()方法,可用具有轉換字元的格式化字串,例如%d表示整數、%f表示浮點數、%s表示字串、%c表示字元、%b表示布林值、%n表示換行
System.out.printf("pi = %.2f%n", 3.1415926);
à pi = 3.14
System.out.printf("pi = %10.2f%n", 3.1415926);
à pi =       3.14
l   輸入:
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner (System.in);
        System.out.print("Please Input Your Name: ");
        // next()
方法取得輸入的字串
        String name = obj.next();
        System.out.print("Please Input Your Age: ");
        // nextInt()
nextFloat()nextBoolean()取得輸入的整數、浮點數、布林值
        int age = obj.nextInt();
        System.out.printf("Hello, %s! Your Age Is %d!%n", name, age);
        System.out.print("Please Input Your Motto: ");
        String motto;
        // nextLine()
方法取得輸入的整行字串
        // equals()
方法比較字串是否相同
        //
前面的next()nextInt()方法不會處理按Enter鍵所產生的換行字元,會使nextLine()方法無法接受新字串,所以使用while迴圈
        while ((motto = obj.nextLine()).equals("")){
            }
        System.out.println("Your Motto Is: " + motto);
        obj.close();
    }
}

三、控制敘述

if選擇敘述
l   單向式範例一:
char a = 'H';
if (a < '0' || a > '9')
    //
敘述區段只有一行可以省略大括號
    System.out.println(a);
l   單向式範例二:
String a = "Hello World";
// equalsIgnoreCase()
方法忽略大小寫的差異
if (a.equals("Poor") | a.equalsIgnoreCase("hello world")){
    //
敘述區段不只一行不可省略大括號
    System.out.println(a);
    System.out.println("Hello Poor World");}
l   雙向式範例:
int max, a = 2, b = 3;
if (a > b){
    max = a;}
else{
    max = b;}
System.out.println(max);
//
上述範例等同於:變數 = 條件式 ? 運算式一 : 運算式二;
max = (a > b) ? a : b;
l   多重判斷式範例:
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner(System.in);
        System.out.print("Please Input a Character: ");
        //
讀取輸入的第一個字元
        char a = obj.next().charAt(0);
        //
亦可用if (Character.isDigit(a))
        if (a >= '0' && a <= '9'){
            System.out.println("It's a Number");}
        //
亦可用else if (Character.isUpperCase(a))
        else if (a >= 'A' && a <= 'Z'){
            System.out.println("It's an Upper-case Character");}
        //
亦可用else if (Character.isLowerCase(a))
        else if (a >= 'a' && a <= 'z'){
            System.out.println("It's a Lower-case Character");}
        else{
            System.out.println("It's a Symbol");}
        obj.close();
    }
}
l   巢狀式:
if
選擇敘述裡面又包含另一個if選擇敘述。

switch多重選擇敘述
l   範例一:
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner(System.in);
        char grade;
        System.out.print("Please Input Exam Score: ");
        int score = obj.nextInt();
        score /= 10;
        switch (score){
            case 10:
            case 9:
            case 8:
                grade = 'A';
                break;
            case 7:
                grade = 'B';
                break;
            case 6:
                grade = 'C';
                break;
            default:
                grade = 'F';}
        System.out.println("The Student Got " + grade + " in the Exam");
        obj.close();
    }
}
l   範例二:
//
若省略break敘述,將不比對後續case值,直接執行接在後面的敘述
// Adults = 500
Reduced Price = 500 * 0.8 = 400Reduced Price Seniors = 500 * 0.8 * 0.7 = 280
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner(System.in);
        System.out.print("Please Input Type of Ticket: 1 for Reduced Price Seniors; 2 for Reduced Price; 3 for Adults: ");
        String type = obj.next();
        int money = 500;
        switch (type){
            case "1":
                money *= 0.7;
            case "2":
                money *= 0.8;
            default:
                System.out.printf("The Ticket Costs %d Dollars", money);}
        obj.close();
    }
}

for迴圈
l   範例:
int sum = 0;
for (int i = 1; i <= 10; i++){
    //
敘述區段只有一行可以省略大括號
    sum += i;}
System.out.println(sum);

while迴圈
l   範例:
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner(System.in);
        int num = 1;
        int sum = 0;
        String numLine = "";
        while (num != 0){
            //
敘述區段只有一行可以省略大括號
            System.out.print("Please Input an Interger to Sum Up (Input 0 to End Calculation): ");
            num = obj.nextInt();
            sum += num;
            numLine += num;
            if (num != 0){
                numLine += " + ";}}
        System.out.printf(numLine + " = " + sum);
        obj.close();
    }
}

do-while迴圈
l   範例:
package testPackage;
import java.util.Scanner;
public class test{
    public static void main(String[] args){
        Scanner obj = new Scanner(System.in);
        String sel;
        //
敘述區段只有一行可以省略大括號
        do{
            System.out.print("Select a Function: A, B, C, D or E: ");
            sel = obj.next().toUpperCase();}
            //
可以查詢比對字串出現的位置,若查詢不到時回傳-1
            while ("ABCDE".indexOf(sel) == -1);
        System.out.println("Function " + sel + " was Selected");
        obj.close();
    }
}

分支敘述-breakcontinuereturn
l   break一般應用範例:
int i = 1, a = 1;
for (i = 0; i < 10; i++){
    a *= 2;
    if (a > 20){
        //
比較System.exit(0);,用於直接結束程式執行
        break;}}
System.out.printf("i = %d, a = %d", i, a);
l   break搭配標記的應用範例:
block: {
    for (int i = 0; i < 10; i++){
        System.out.println("Hello World");
        if (i == 1){
            break block;}
        System.out.println("Hello Poor World");}}
l   continue一般應用範例:
for (int i = 0; i <= 10; i++){
    if (i % 2 == 0){
        continue;}
    System.out.print(i + ", ");}
l   continue搭配標記的應用範例:
int i, j, a = 0;
int[][] b = {{1, 0, 0, 1, 0}, {1, 0, 1, 1, 0}, {1, 1, 0, 1, 1}};
Block:
    for (i = 0; i < 3; i++){
        for (j = 0; j < 5; j++){
            if (b[i][j] == 0){
                continue Block;}
            else{
                a += 1;}}}
System.out.print("There are " + a + " 1 Before 0");

四、陣列

陣列宣告與初始元素個數
l   不宣告初始元素個數:
//
建議此種宣告方式
int[] a;
int []b;
int c[];
l   宣告初始元素個數:
//
建議此種宣告方式
int[] a = new int[3];
int []b = new int[3];
int c[] = new int[3];

指定陣列元素
l   指定方式一:
int[] a = new int[3];
a[0] = 11;
a[1] = 22;
a[2] = 33;
l   指定方式二,此種方式不可宣告初始元素個數:
//
等同int[] a = {11, 22, 33};
int[] a = new int[] {11, 22, 33};
l   指定方式三,如果陣列元素都相同,可使用Array.fill()方法:
package testPackage;
import java.util.Arrays;
public class test{
    public static void main(String[] args){
        int[] a = new int[6];
        // Arrays.fill(
陣列名稱, 元素值);
        Arrays.fill(a, 100);
        System.out.println(a[0] + a[1] + a[2] + a[3] + a[4] + a[5]);
    }
}

存取陣列元素
l   使用for迴圈存取陣列元素:
int[] a = {11, 22, 33};
//
可用a.length取得陣列元素個數
//
陣列用的是a.length,字串用的是b.length()
for (int i = 0; i < a.length; i++){
    System.out.println(a[i]);}
l   使用for-each迴圈存取陣列元素:
for-each(for/in)
迴圈是Java SE5.0版本以後新增的語法,專門用來存取陣列或集合(collection)中的元素。
int[] a = {11, 22, 33};
for (int i : a){
    System.out.println(i);}

多維陣列
l   多維陣列宣告與初始元素個數:
int[][] a = new int[3][4];
l   指定多維陣列元素:
//
等同int[][] a = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10,11}};
int[][] a = new int[][] {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10,11}};
l   使用for迴圈存取多維陣列元素:
int[][] a = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10,11}};
for (int i = 0; i < a.length; i++){
    for (int j = 0; j < a[i].length; j++){
        System.out.print(a[i][j] + ", ");}
    System.out.println();}
l   使用for-each迴圈存取多維陣列元素:
int[][] a = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10,11}};
for (int[] i : a){
    for (int j : i){
        System.out.print(j + ", ");}
    System.out.println();}

Arrays類別的基本應用
l   使用前必須載入:import java.util.Arrays;
l   sort遞增排序方法:
int[] a = {1, 9, 6, 2, 8, 4};
Arrays.sort(a);
for (int i : a){
    System.out.print(i + ", ");}
l   sort遞減排序方法:
//
必須額外載入:import java.util.Collections;
//
必須使用Integer[]取代int[]
Integer[] a = {1, 9, 6, 2, 8, 4};
Arrays.sort(a, Collections.reverseOrder());
for (int i : a){
    System.out.print(i + ", ");}
l   binarySearch方法:
如果找到資料,傳回該資料的註標值;如果找不到資料,會將若該資料排序插入陣列,傳回的註標值的負值再減1
int[] a = {1, 2, 3, 5, 6};
int b = Arrays.binarySearch(a, 2);
System.out.println(b);
à 1
int c = Arrays.binarySearch(a, 4);
System.out.println(c);
à -4

取得陣列與命令列的資料
l   在命令提示字元切換至test.class所在目錄,輸入java test pearl bigPearl stardust starPiece等引數即可;若在eclipse整合環境中,執行Run/Run Configurations...指令,在(x)=Arguments標籤頁中輸入引數亦可。
l   範例:
//
顯示命令列的資料
for (int i = 0; i < args.length; i++){
    System.out.println("Command Line Data No." + (i + 1) + ": " + args[i]);}
//
顯示陣列的資料
String[] itemData = {"tinyMushroom", "bigMushroom", "nugget"};
for (int j = 0; j < itemData.length; j++){
    System.out.println("Array Data No." + (j + 1) + ": " + itemData[j]);}

五、方法

方法的語法
l   語法:
修飾子 static 傳回值型別 方法名稱(引數串列) throws 例外名稱{
    ......
   
程式區段;
    return
運算式;
    ......
}
l   修飾子:
private
protectedpublicdefault4種,預設為default
l   static
靜態方法,不需再使用new來建立該類別的物件實體就可以直接使用。
l   傳回值型別:
不傳回任何資料就用void
l   方法名稱:
除了要符合識別字規定之外,通常用駝峰式命名。
l   引數串列:
省略引數串列表示呼叫此方法不需傳入任何值。
l   throws 例外名稱:
宣告某個方法可能會拋出的例外。
l   程式區段:
方法的主體。
l   return 運算式:
執行方法後要傳回的值,應和方法的傳回值型別一致。

呼叫方法
l   呼叫同類別、不同類別的靜態方法:
package testPackage;
class test2{
    static void add(int x, int y){
        System.out.println("test2 add: " + x + " + " + y + " = " + (x + y));
    }
}
public class test{
    static void add(int a, int b){
        System.out.println("test add: " + a + " + " + b + " = " + (a + b));
    }
    public static void main(String[] args){
        //
呼叫同類別的靜態方法
        add(5, 3);
        //
呼叫不同類別的靜態方法
        test2.add(7, 2);
    }
}
l   必須建立實體物件,才能呼叫同類別、不同類別的非靜態方法:
package testPackage;
class test2{
    void add(int x, int y){
        System.out.println("test2 add: " + x + " + " + y + " = " + (x + y));
    }
}
public class test{
    void add(int a, int b){
        System.out.println("test add: " + a + " + " + b + " = " + (a + b));
    }
    public static void main(String[] args){
        //
建立實體物件,呼叫同類別的非靜態方法
        test c = new test();
        c.add(5, 3);
        //
建立實體物件,呼叫不同類別的非靜態方法
        test2 z = new test2();
        z.add(7, 2);
    }
}

傳值呼叫與參考呼叫
l   傳值呼叫(Call by Value)-引數為基本資料型別:
package testPackage;
public class test{
    static void byVal(int x, int y){
        x += 3;
        y += 2;
        System.out.println("Now Call by Value: x = " + x + ", y = " + y);
    }
    public static void main(String[] args){
        int a = 10, b = 15;
        System.out.println("Before Call by Value: a = " + a + ", b = " + b);
        byVal(a, b);
        System.out.println("After Call by Value: a = " + a + ", b = " + b);
    }
}
l   參考呼叫(Call by Reference)-引數為陣列、物件等:
package testPackage;
class test2{
    int a = 10, b = 15;
}
public class test{
    static void byRef(test2 z){
        z.a += 3;
        z.b += 2;
        System.out.println("Now Call by Reference: x = " + z.a + ", y = " + z.b);
    }
    public static void main(String[] args){
        test2 c = new test2();
        System.out.println("Before Call by Reference: a = " + c.a + ", b = " + c.b);
        byRef(c);
        System.out.println("After Call by Reference: a = " + c.a + ", b = " + c.b);
    }
}

方法多載(Method Overloading)
l   同一個類別中,允許方法使用相同的名稱,但是後面所接的引數串列必須至少符合其一:一、資料型別不同;二、個數不同;三、順序不同。
l   範例:
package testPackage;
public class test{
    static int add(int a, int b){
        return a + b;
    }
    static double add(double a, double b, double c){
        return a + b + c;
    }
    public static void main(String[] args){
        System.out.println(add(10, 15));
        System.out.println(add(1.3, 5.6, 45.3));
    }
}

省略引數個數的語法
l   當方法多載時,會以資料型別與引數個數都相同的方法優先執行,擁有省略號的方法次之;一個方法中只能有一個省略號,而且必須置於最後面的引數。
l   範例:
package testPackage;
public class test{
    static int add(int... a){
        int sum = 0;
        for (int i : a){
            sum += i;}
        return sum;
    }
    public static void main(String[] args){
        System.out.println(add(1, 2));
        System.out.println(add(1, 2, 3));
        System.out.println(add(1, 2, 3, 4));
    }
}

遞迴(Recursive)
l   範例:
package testPackage;
public class test{
    static int fib(int a){
        if (a == 1 || a == 2){
            return 1;}
        else{
            return fib(a - 1) + fib(a - 2);}
    }
    public static void main(String[] args){
        //
隨機產生150之間的數值
        int n = (int) (Math.random() * 50) + 1;
        System.out.println("Fibonacci No." + n + ": " + fib(n));
    }
}

六、物件與類別

類別的語法
l   語法:
類別存取修飾子 class 類別名稱{
   
成員存取修飾子 static 資料型別 資料成員名稱 = 初值;
    ...
   
成員存取修飾子 static 傳回值型別 方法成員名稱(引數串列){
    ...
    }
    ...
}
l   類別存取修飾子:
public與預設階層(不宣告)2種,public可在不同套件(Package)使用,若為預設階層,只能在相同套件使用;一個.java檔可以定義多個類別,但只能宣告一個public類別,且public的類別名稱必須和.java檔檔名相同。
l   成員存取修飾子:
private
protectedpublicdefault4種,private只供自身類別內部成員存取,protected只供自身類別或繼承自身類別的子類別內部成員存取,至於public則不受任何限制。
l   若資料成員未設定初值:
若資料成員為數值型別,預設值為0
若資料成員為字串型別,預設值為""(空字串)
若資料成員為布林型別,預設值為false

privatepublic成員存取修飾子
l   範例:
package testPackage;
class test2{
    private double sum = 0;
    private void calAdd(double... i){
        for (double j : i){
            sum += j;}
    }
    public double add(double a, double b, double c, double d){
        calAdd(a, b, c, d);
        return sum;
    }
}
public class test{
    public static void main(String[] args){
        // test2 obj;
宣告obj物件屬於test2類別
        // obj = new test2();
建立出obj物件實體
        test2 obj = new test2();
        System.out.println(obj.add(5.5, 3.3, 7.7, 2.2));
    }
}

static靜態資料成員與方法成員
l   呼叫同類別、不同類別的靜態資料成員、靜態方法成員:
package testPackage;
class test2{
    //
不同類別的靜態資料成員
    static int ba = 42;
    //
不同類別的靜態方法成員
    static int bAdd(int bb, int bc){
        return bb + bc;
    }
}
public class test{
    //
同類別的靜態資料成員
    static int aa = 21;
    //
同類別的靜態方法成員
    static int aAdd(int ab, int ac){
        return ab + ac;
    }
    public static void main(String[] args){
        //
呼叫同類別的靜態資料成員
        System.out.println(aa);
        //
呼叫同類別的靜態方法成員
        System.out.println(aAdd(5, 3));
        //
呼叫不同類別的靜態資料成員
        System.out.println(test2.ba);
        //
呼叫不同類別的靜態方法成員
        System.out.println(test2.bAdd(10, 6));
    }
}
l   必須建立實體物件,才能呼叫同類別、不同類別的非靜態資料成員、非靜態方法成員:
package testPackage;
class test2{
    //
不同類別的非靜態資料成員
    int ba = 42;
    //
不同類別的非靜態方法成員
    int bAdd(int bb, int bc){
        return bb + bc;
    }
}
public class test{
    //
同類別的非靜態資料成員
    int aa = 21;
    //
同類別的非靜態方法成員
    int aAdd(int ab, int ac){
        return ab + ac;
    }
    public static void main(String[] args){
        test obj = new test();
        //
建立實體物件,呼叫同類別的非靜態資料成員
        System.out.println(obj.aa);
        //
建立實體物件,呼叫同類別的非靜態方法成員
        System.out.println(obj.aAdd(5, 3));
        test2 obj2 = new test2();
        //
建立實體物件,呼叫不同類別的非靜態資料成員
        System.out.println(obj2.ba);
        //
建立實體物件,呼叫不同類別的非靜態方法成員
        System.out.println(obj2.bAdd(10, 6));
    }
}

方法多載(Method Overloading)
l   範例:
package testPackage;
class test2{
    public int getMax(int a, int b){
        if (a > b){
            return a;}
        else{
            return b;}
    }
    public int getMax(int[] aArray){
        int num = aArray[0];
        for(int i = 1; i < aArray.length; i++){
            if (aArray[i] > num){
                num = aArray[i];}}
        return num;
    }
}
public class test{
    public static void main(String[] args){
        int[] aNumArray = {52, 66, 78, 99, 11};
        test2 obj = new test2();
        System.out.println(obj.getMax(10, 20));
        System.out.println(obj.getMax(aNumArray));
    }
}

建構式(Constructor)
l   在建立物件時,建構式能同時傳遞引數來進行資料成員初始化工作;建構式定義方式與方法相同,但建構式名稱必須和所屬類別名稱相同,不能使用returnvoid等傳回值型別,也不能使用staticfinalabstract等修飾子,若類別內未定義建構式,系統會自動提供一個不帶引數的預設建構式。
l   範例:
package testPackage;
class test2{
    private int height = 150, weight = 40;
    private void setHeight(int h){
        if (h >= 50 && h <= 250){
            height = h;}
    }
    private void setWeight(int w){
        if (w >= 30 && w <= 150){
            weight = w;}
    }
    public test2(){
    }
    public test2(int h){
        setHeight(h);
    }
    public test2(int h, int w){
        setHeight(h);
        setWeight(w);
    }
    public void showData(){
        System.out.println("Height: " + height);
        System.out.println("Weight: " + weight);
    }
}
public class test{
    public static void main(String[] args){
        test2 aPerson = new test2();
        aPerson.showData();
        test2 bPerson = new test2(300);
        bPerson.showData();
        test2 cPerson = new test2(180, 70);
        cPerson.showData();
    }
}

this參考自身類別
l   可以利用this這個保留字來解決名稱重複的問題,清楚得知這個成員屬於類別中的成員。
l   範例:
package testPackage;
class test2{
    private int a;
    public void showNum(int a){
        this.a = a;
        a += 2;
        System.out.println(this.a);
        System.out.println(a);
    }
}
public class test{
    public static void main(String[] args){
        test2 obj = new test2();
        obj.showNum(20);
    }
}

沒有留言:

張貼留言