什麼是「自訂類別」
在 Java 中,我們可以自己定義一個類別(class)來描述某個事物的屬性(成員變數)和行為(方法)。這就叫做自訂類別,是物件導向的基礎。
類別 vs 物件
| 名稱 |
是什麼? |
範例 |
| 類別(Class) |
藍圖 |
class Student {} |
| 物件(Object) |
真正的實體 |
Student s1 = new Student(); |
如何定義一個類別
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Student { String name; int age;
void sayHi() { System.out.println("Hi! 我是 " + name); } }
public class Main { public static void main(String[] args) { Student s1 = new Student(); s1.name = "小明"; s1.age = 18; s1.sayHi(); } }
|
輸出結果:
記憶體說明(Stack vs Heap)
1
| Student s = new Student();
|
| 區域 |
儲存什麼 |
| Stack |
變數 s,存放記憶體地址 |
| Heap |
實際的 Student 物件(name, age…) |
建構子 Constructor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Student { String name; int age;
Student(String n, int a) { name = n; age = a; }
void sayHi() { System.out.println("我是 " + name + ",今年 " + age + " 歲"); } }
public class Main { public static void main(String[] args) { Student s = new Student("小華", 17); s.sayHi(); } }
|
Student 類別:
- 定義了兩個屬性:
name 和 age
- 建構子接收姓名和年齡來初始化物件
sayHi() 方法用來自我介紹
Main 類別:
- 建立一個名為”小華”、17歲的 Student 物件
- 呼叫
sayHi() 方法
執行結果
我是 小華,今年 17 歲
關鍵概念
- 建構子:
Student(String n, int a) 在建立物件時自動執行
- 物件建立:
new Student("小華", 17) 建立實體
- 方法呼叫:
s.sayHi() 執行物件的行為
this 關鍵字
this 代表「當前物件本身」,用來區分參數和屬性。
問題:參數和屬性同名怎麼辦
1 2 3 4 5 6 7 8 9
| class Student { String name; int age;
Student(String name, int age) { name = name; age = age; } }
|
問題:Java 分不清楚你要的是「屬性」還是「參數」,預設會使用「參數」。
解決方案:使用 this
1 2 3 4 5 6 7 8 9
| class Student { String name; int age;
Student(String name, int age) { this.name = name; this.age = age; } }
|
解釋:
this.name = 物件的屬性
name = 建構子的參數
this 的三種用法
1. 區分屬性和參數(最常用)
1 2 3
| public Student(String name) { this.name = name; }
|
2. 呼叫其他方法
1 2 3
| public void introduce() { this.printName(); }
|
3. 呼叫其他建構子
1 2 3 4 5 6 7 8
| public Student(String name) { this(name, 18); }
public Student(String name, int age) { this.name = name; this.age = age; }
|
完整範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Student { String name; int age;
public Student(String name, int age) { this.name = name; this.age = age; }
public void introduce() { System.out.println("我是 " + this.name + "," + this.age + " 歲"); } }
|
重點
this = 當前物件
- 主要用來解決「同名衝突」
- 讓程式碼更清楚易讀
常見錯誤觀念澄清
| 錯誤觀念 |
正確觀念 |
| 物件等於類別 |
❌ 物件是由類別產生的實體 |
| 類別不能有同名方法 |
❌ 可以「多載 overload」 |
| 屬性不用初始化 |
❌ 建議在建構子中初始化 |
| this 是 Java 保留變數 |
✅ 是參考「自己的」關鍵字 |
重點整理
- 自訂類別就是自創一種資料型別(描述屬性+行為)
- 類別是藍圖,物件是實體(用
new 建立)
- 資料放在 Heap,變數位址放在 Stack
- 建構子在建立物件時自動執行
this 代表目前物件本身,常用來解決命名衝突
什麼是方法
Java 中,「方法」是物件的功能、動作、行為。
方法基本語法
範例:
1 2 3
| void sayHi() { System.out.println("Hi!"); }
|
有參數的方法
1 2 3
| void sayHiTo(String name) { System.out.println("Hi, " + name); }
|
有回傳值的方法
1 2 3
| int add(int a, int b) { return a + b; }
|
有參數 + 有回傳值
1 2 3
| double bmi(double w, double h) { return w / (h * h); }
|
方法分類
| 類型 |
說明 |
範例 |
| 無參數無回傳值 |
執行某件事但不給資料 |
void sayHi() |
| 有參數無回傳值 |
根據參數做事但不回資料 |
void sayHiTo(String name) |
| 無參數有回傳值 |
做事後給你一個值 |
int getAge() |
| 有參數有回傳值 |
根據參數做事並回傳結果 |
double bmi(double w, h) |
物件呼叫方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Student { String name; int age;
Student(String n, int a) { name = n; age = a; }
void sayHi() { System.out.println("我是 " + name); } }
public class Main { public static void main(String[] args) { Student s = new Student("小華", 17); s.sayHi(); } }
|
return 是什麼
return 把結果「丟回去」給呼叫的人。
1 2 3 4 5 6 7 8 9 10
| public class Main { public static void main(String[] args) { int result = doubleNum(5); System.out.println(result); }
static int doubleNum(int x) { return x * 2; } }
|
特別注意
有明確定義建構式時,不會自動產生預設空白建構式,所以需要手動定義預設建構式
1 2 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 42 43 44 45 46 47 48 49 50 51
| package math.geometry;
public class Point { public int x; public int y; public Point(int x) { this.x = x; this.y = 10; } public Point(int x, int y) { this.x = x; this.y = y; } public Point() { this.x = 0; this.y = 0; } public void render() { System.out.println(this.x + ", " + this.y); } }
class App { public static void main(String[] args) { Point p1 = new Point(6); p1.render(); Point p2 = new Point(3, 4); p2.render(); Point p3 = new Point(); p3.render(); } }
|