介紹
這一篇是 Java 基本語法介紹的第三篇,我們要來繼續探討程式碼架構。
Vector 類別
Vector 是一種可以自動增減長度的「動態陣列」,屬於 java.util 套件的一部分,它的概念類似於 ArrayList,但 Vector 是執行緒安全 (synchronized) 的版本,因此在多執行緒環境中使用更安全,但效能稍慢一些 。
與 ArrayList 相比的主要差異是 Vector 所有操作方法都加上同步鎖定 (synchronized)。
常用的方法統整:
| 方法 | 功能說明 | 
| add(E e) | 在尾端新增元素 | 
| add(int index, E e) | 在指定位置加入元素 | 
| get(int index) | 取得指定位置的元素 | 
| remove(int index) | 移除指定位置的元素 | 
| size() | 回傳目前元素個數 | 
| capacity() | 回傳目前容量大小 | 
| clear() | 清空所有內容 | 
| contains(Object o) | 檢查是否包含指定元素 | 
| iterator() | 回傳用於遍歷的 Iterator | 
範例:
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | Vector<String> fruits = new Vector<>();fruits.add("Apple");
 fruits.add("Banana");
 fruits.add("Mango");
 
 System.out.println(fruits);
 System.out.println(fruits.get(1));
 fruits.remove("Apple");
 System.out.println(fruits.size());
 
 | 
例外
例外處理
我們在執行程式的過程中,有時會有發生錯誤的時候,這時我們可以使用例外處理機制來攔截執行期間的錯誤。
以下是常見的例外 (Exception):
| 錯誤代碼 | 意思 | 
| ArrayIndexOutOfBoundsException | 陣列索引值超出範圍 | 
| ArithmeticException | 運算時產生的錯誤,例如除數為 0 | 
| ArrayStoreException | 指定陣列內容時產生的錯誤 | 
| ClassCastException | 類別轉換錯誤 | 
| ClassNotFoundException | 找不到指定的類別 | 
| CloneNotSupportException | 在類別中使用 clone(),但該類別尚未實作 Cloneable 介面 | 
| FileNotFoundException | 找不到指定檔案 | 
| InterruptedException | 另一個執行緒試圖使用 Interrupt() 來中斷已停止的執行緒 | 
| IOException | 檔案、網路輸入輸出產生的錯誤 | 
| IllegalArgumentException | 呼叫方法時傳遞錯誤的參數 | 
| IndexOutOfBoundsException | 索引值超出範圍 | 
| NullPointerException | 使用物件時,該物件的參考值為 null | 
| NumberFormatException | 字串轉數字產生的錯誤 | 
| SecurityException | 違反安全性限制 | 
如何判斷錯誤並執行例外處理:
| 12
 3
 4
 5
 6
 7
 
 | try {程式執行區塊
 }catch (例外名稱){
 例外處理的程式碼區塊
 }finally{
 最後執行的程式區塊
 }
 
 | 
範例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | import java.util.InputMismatchException;import java.util.Scanner;
 
 try (Scanner scanner = new Scanner(System.in)) {
 System.out.print("請輸入分子數:");
 int a = scanner.nextInt();
 System.out.print("請輸入分母數:");
 int b = scanner.nextInt();
 System.out.println(a + "除以" + b + "等於:" + a / b);
 } catch (ArithmeticException e) {
 System.out.println("錯誤代碼: " + e.getClass().getSimpleName());
 System.out.println("除數不能為0");
 } catch (InputMismatchException e) {
 System.out.println("輸入的數值必須為整數數值");
 }
 
 | 
拋出例外 Throw & Throws
程式執行的過程中,所引發的錯誤例外,都是由 Java 的虛擬機 (JVM) 來自動產生錯誤提示的例外。
我們也可以自行產生指定的例外,來提供程式判斷與處理這些例外。
自行產生例外有兩種方式:
- throw: 在程式中產生一個例外物件。
- throws: 宣告一個類別的方法,並指定該方法可以產生一個例外物件。
範例:
| 12
 3
 4
 5
 6
 7
 8
 
 | try {String myText = "Hello, World!";
 if (myText.equals("Hello, World!")) {
 throw new ArithmeticException("自己產生的錯誤例外");
 }
 } catch (ArithmeticException e) {
 System.out.println("捕捉到 ArithmeticException: " + e.getMessage());
 }
 
 | 
如果在方法內發生錯誤,但方法內沒有 try ... catch ... 的例外處理,就可以在方法宣告時使用 throws 將例外產生,讓呼叫該方法的那一層來處理。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public class Main {public int divide(int a, int b) throws ArithmeticException {
 return a / b;
 }
 
 public static void main(String[] args) {
 Main t = new Main();
 try {
 System.out.println(t.divide(10, 0));
 } catch (ArithmeticException ex) {
 System.out.println("發生運算錯誤");
 }
 }
 }
 
 | 
自訂例外
Exception 是一個類別。裡面有各種例外物件的類別型態。如果想要建立自己的例外類別,來處理特殊的情況,可以使用繼承 Exception 類別,產生自訂例外類別。
產生自訂例外類別的方法如下:
| 12
 3
 4
 5
 
 | class MyException extends Exception {...}
 
 
 class MyException_2 extends RuntimeException {...}
 
 | 
Exception 可用的 Throwable 方法:
| 方法 | 功能 | 回傳值資料型態 | 
| fillnStackTrace() | 回傳包含完整堆疊追蹤的 Throwable 物件 | Throwable | 
| getCause() | 回傳造成例外原因的 Throwable 物件 | Throwable | 
| getMessage()/getLocalizedMessage() | 回傳例外訊息說明 | String | 
| getStackTrace() | 回傳包含堆疊追蹤的陣列 | StackTraceTlement[ ] | 
| initCause(Throwable cause) | 將 cause 當作是例外發生的原因 | Throwable | 
| printStackTrace() | 顯示堆疊追蹤 | void | 
| printStackTrace(PrintStream ps) | 將堆疊追蹤顯示在 PrintStream 類別串流物件上 | void | 
| printStackTrace(PrintWriter pw) | 將堆疊追蹤顯示在 PrintWriter 類別串流物件上 | void | 
| setStackTrace(StackTraceElement[] ste) | 設定堆疊追蹤元素由 getStackTrace 的方法回傳,由 printStackTrace 的方法顯示 | void | 
| toString() | 回傳簡短的例外描述字串 | String | 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | class UserException extends Exception {private String errCode;
 private String errMessage;
 
 public UserException(String errCode) {
 this.errCode = errCode;
 errMessage="這是一個自訂例外!!";
 }
 public String getErrCode() {
 return errCode;
 }
 public String getMessage() {
 return errMessage;
 }
 }
 public class Main {
 
 public void throwUserException() throws UserException {
 throw new UserException("001");
 }
 public static void main(String[] args) {
 Main test = new Main();
 try {
 test.throwUserException();
 } catch (UserException e) {
 System.out.println("錯誤碼:" + e.getErrCode());
 System.out.println("錯誤訊息:" + e.getMessage());
 }
 }
 }
 
 | 
Math
Java 將較常使用的數學函式,製作成方法,封裝於 Java.lang 套件中的 Math 類別。屬於 Java 的預設套件,所以 Java 會自動引入該套件。
常數
Math 類別定義了兩個數學常數,分別是自然對數 (E) 與圓周率的 (PI)。
| 常數名稱 | 資料類型 | 值 | 
| E | double | 2.71828182… | 
| PI | double | 3.141592653… | 
方法
| 方法 | 功能 | 
| random() | 隨機數 | 
| pow(a, b) | 次方 | 
| sqrt(a) | 平方根 | 
| min(a, b) | 回傳最小值 | 
| max(a, b) | 回傳最大值 | 
| abs(a) | 回傳絕對值 | 
| toDegrees(angrad) | 回傳弧度的角度 | 
| toRadians(angdeg) | 回傳角度的弧度 | 
| sin(a) | 正弦函數 | 
| cos(a) | 餘弦函數 | 
| tan(a) | 正切函數 | 
| asin(a) | 反正弦函數 | 
| acos(a) | 反餘弦函數 | 
| atan(a) | 反正切函數 | 
| exp(a) | 回傳指數 | 
| log(a) | log | 
| log10(a) | log10 | 
使用方式
使用 Math 類別底下的函式,Math.<方法>。
| 12
 3
 
 | double value = Math.pow( 2, 10 ); System.out.println( "2 的 10 次方 = " + value);
 System.out.println( value + "開根號的結果 = "+Math.sqrt(value));
 
 | 
Object
物件的建構
物件是一個參考類型,所以在宣告物件名稱的時候,不會配置實際的記憶體空間。因此,必須要用 new 來建立記憶體空間並將物件指向記憶體位址。
格式如下:
建構子
建構子是類別內的方法,建構子有兩種型態,分別是有參數與無參數型態。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | public class Car {private String brand;
 private String model;
 
 
 public Car() {
 this.brand = "Toyota";
 this.model = "Corolla";
 }
 
 
 public Car(String brand, String model) {
 this.brand = brand;
 this.model = model;
 }
 
 public void displayInfo() {
 System.out.println("Brand: " + brand + ", Model: " + model);
 }
 
 public static void main(String[] args) {
 
 Car car1 = new Car();
 car1.displayInfo();
 
 
 Car car2 = new Car("Honda", "Civic");
 car2.displayInfo();
 }
 }
 
 | 
方法的多載 Overload
在同一個類別中,可以定義多個相同名稱的方法但傳入的參數不同。讓我們可以使用不同的引數組合來呼叫同一功能。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 
 | package com.raylon;
 public class Main {
 public void sayHello() {
 System.out.println("Hello, World!");
 }
 
 public void sayHello(String name) {
 System.out.println("Hello, " + name + "!");
 }
 
 public void sayHello(String name, int times) {
 for (int i = 0; i < times; i++) {
 System.out.println("Hello, " + name + "!");
 }
 }
 
 public void sayHello(int times) {
 for (int i = 0; i < times; i++) {
 System.out.println("Hello");
 }
 }
 
 public static void main(String[] args) {
 Main obj = new Main();
 obj.sayHello();
 obj.sayHello("Alice");
 obj.sayHello("Bob", 3);
 obj.sayHello(2);
 }
 }
 
 | 
參數的「型態」、「數量」或「順序」必須要有一項不同。
This 指標
this 是自己,代表當前的類別或物件,在方法當中可以使用 this.<屬性名稱/方法名稱> 來呼叫當前類別或物件中的屬性或方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | class Subject {int subjectNo;
 String chiName,engName;
 int credit = 2;
 Subject(int subjectNo,String chiName,String engName){
 this.subjectNo = subjectNo;
 this.chiName = chiName;
 this.engName = engName;
 }
 Subject(int subjectNo,String chiName,String engName, int credit){
 this(subjectNo, chiName, engName);
 this.credit = credit;
 }
 void display( ){
 System.out.printf( "課程: %d-%s (%s), 學分數:%d \n",
 subjectNo, chiName, engName, credit );
 }
 }
 class Main {
 public static void main(String args[]){
 Subject s1=new Subject(112, "運算思維", "Python");
 Subject s2=new Subject(111, "程式設計", "java", 3);
 s1.display();
 s2.display();
 }
 }
 
 | 
繼承
透過繼承,子類別建構的物件會有父類別的特性。
繼承的規則
- 父類別宣告為 final 的屬性或方法,子類別不能覆寫。
- 父類別宣告為 private 的屬性或方法,子類別無法繼承使用。
- 父類別宣告為 abstract 的方法,必須要在子類別內實作。
使用方式
語法:
| 12
 3
 
 | class 子類別名稱 extends 父類別名稱 {子類別的方法
 }
 
 | 
範例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | class Compute {public void times (int x, int y){
 System.out.println(x+"*"+y+"="+(x*y));
 }
 public void divided (int x, int y){
 System.out.println(x+"/"+y+"="+(float)x/y);
 }
 }
 class Accounting extends Compute{
 public void plus (int x, int y){
 System.out.println(x+"+"+y+"="+(x+y));
 }
 public void minus (int x, int y){
 System.out.println(x+"-"+y+"="+(x-y));
 }
 }
 public class Main {
 public static void main(String[] args){
 Accounting myObj = new Accounting();
 myObj.plus(200,30);
 myObj.minus(200,30);
 myObj.times(200,30);
 myObj.divided(200,30);
 }
 }
 
 | 
建構子的執行順序
會先把父類別建構完畢才會建構子類別。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | class TestA{TestA( ){ System.out.println("這是類別 A");
 }
 }
 class TestB extends TestA{
 TestB( ){
 System.out.println("這是繼承類別 A 的類別 B");
 }
 }
 class TestC extends TestB{
 TestC( ){
 System.out.println("這是繼承類別 B 的類別 C");
 }
 }
 public class Main {
 public static void main(String[] args){
 System.out.println("【單一繼承的建構子執行順序示範:】");
 TestB b = new TestB( );
 System.out.println("【多重繼承的建構子執行順序示範:】");
 TestC c = new TestC( );
 }
 }
 
 | 
覆寫
如果子類別中的方法名稱、傳遞參數和回傳值類型都與父類別中的方法相同時,就會進行覆寫 (Override)。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | public class Main {public static void main(String[] args){
 Plane747 CAL=new Plane747();
 CAL.setData(4000.5,"藍色");
 CAL.setLane(5);
 CAL.display();
 }
 }
 class AirPlane{
 double fuel;
 String color;
 public void setData(double fuel, String color){
 this.fuel=fuel;
 this.color=color;
 }
 public void display(){
 System.out.println("飛機可裝載燃料數量:"+fuel);
 System.out.println("飛機顏色:"+color);
 }
 }
 
 class Plane747 extends AirPlane{
 private int airLane;
 public void setLane(int airLane){
 this.airLane=airLane;
 }
 
 public void display(){
 System.out.println("747飛機可裝載油料 " + fuel + " 公升");
 System.out.println("747飛機的顏色是 " + color);
 System.out.println("747飛機起飛的跑道是 " + airLane);
 }
 }
 
 | 
Super 指標
在 Java 中,可以使用 this 代表當前的類別;如果想要使用父類別的方法,就可以使用 super 代表上一層的類別。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | public class Main extends Human{  public static void main(String[] args){
 Main crew = new Main( );
 crew.setName("張三");
 crew.setAge(21);
 crew.print();
 }
 public void print(){
 System.out.print("【職員】");
 super.print();
 }
 }
 class Human{
 private String name;
 private int age;
 protected void setName(String name){
 this.name=name;
 }
 protected void setAge(int age){
 this.age=age;
 }
 protected void print(){
 System.out.printf("姓名:%s, 年齡:%n ", name, age);
 }
 }
 
 | 
多型
多型 (Polymorphism) 是指同一個物件,在不同的情況下,可以表現出不同的行為。目的是讓程式更有彈性、可擴充性、可維護性。主要是透過抽象的類別繼承與介面的實作,讓不同類型的物件可以實作同一個介面,並根據不同的情況呼叫對應的方法。
抽象類別
抽象類別是指含有抽象方法的類別,抽象方法只是事前先宣告方法名稱、參數與回傳的資料型態,還沒有實作。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 
 | abstract class Animal {String name;
 int age;
 public Animal(String name, int age) {
 this.name = name;
 this.age = age;
 }
 abstract void makeSound();
 public void printInfo() {
 System.out.println("名字: " + name);
 System.out.println("年齡: " + age);
 }
 }
 class Dog extends Animal {
 public Dog(String name, int age) {
 super(name, age);
 }
 void makeSound() {
 System.out.println("汪汪!");
 }
 }
 class Cat extends Animal {
 public Cat(String name, int age) {
 super(name, age);
 }
 void makeSound() {
 System.out.println("喵喵!");
 }
 }
 public class Main {
 public static void main(String[] args) {
 Animal myDog = new Dog("來福", 3);
 Animal myCat = new Cat("來喜", 2);
 
 myDog.makeSound();
 myDog.printInfo();
 
 myCat.makeSound();
 myCat.printInfo();
 }
 }
 
 | 
介面
介面 (interface) 是一個完全沒有任何方法被實作的抽象類別。介面是一個類別,裡面所有宣告的方法都必須是抽象的。因此,在繼承類別時必須實作介面中的所有方法。
語法:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | interface 介面名稱 {[ 修飾語 ] 資料類型 常數名稱 = 值;
 ......
 [ 修飾語 ] 回傳值類型 介面方法名稱(參數, ...);
 ......
 }
 
 class 類別名稱 implements 介面名稱1, 介面名稱2, ... {
 實作介面的方法;
 }
 
 | 
範例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | interface IPet {public String attr = "可愛";
 void skill( );
 void action( );
 }
 class Puppy implements IPet {
 public void skill( ) {
 System.out.println( attr+",撒嬌");
 }
 public void action( ) {
 System.out.println("追趕跑跳碰");
 }
 }
 public class Main {
 public static void main(String[] args){
 Puppy myPet = new Puppy( );
 myPet.skill( );
 myPet.action( );
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | interface IRequest {void execute();
 }
 class HelloRequest implements IRequest {
 private String name;
 public HelloRequest(String name) {
 this.name = name;
 }
 public void execute() {
 System.out.println("您好," + name);
 }
 }
 class WelcomeRequest implements IRequest {
 private String place;
 public WelcomeRequest(String place) {
 this.place = place;
 }
 public void execute() {
 System.out.println("歡迎光臨" + place);
 }
 }
 public class Main {
 public static void main(String[] args) {
 int n;
 for(int i = 0; i < 6; i++) {
 n = (int) (Math.random() * 2) +1;
 if (n == 1)
 doRequest( new HelloRequest("張三"));
 else
 doRequest(new WelcomeRequest("某大學"));
 }
 }
 public static void doRequest(IRequest request) {
 request.execute();
 }
 }
 
 | 
繼承類別與介面
繼承類別使用 extends;繼承介面使用 implements,同時進行繼承類別與介面時要先宣告 extends 再宣告 implements。
語法:
| 12
 3
 
 | class 類別名稱 extends 父類別名稱 implements 介面名稱1, 介面名稱2, ... {實作介面的方法;
 }
 
 | 
範例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | interface Engine {public void start( );
 public void stop( );
 }
 class Gearbox {
 public void shiftUp( ) {
 System.out.println("進檔");
 }
 public void shiftDown( ) {
 System.out.println("退檔");
 }
 }
 class Car extends Gearbox implements Engine {
 public void start( ) {
 System.out.println("發動引擎");
 }
 public void stop( ) {
 System.out.println("停止引擎");
 }
 }
 public class Main {
 public static void main(String[] args) {
 Car myCar = new Car( );
 myCar.start( );
 myCar.shiftUp( );
 myCar.shiftDown( );
 myCar.stop( );
 }
 }
 
 |