從零開始的JAVA-伊始之地
===
###### tags: `程式設計` `JAVA`
:::success
🤖 本篇由 [**chatGPT**](https://platform.openai.com/) 及 [**Mai.Coding**](https://hackmd.io/@0x0607) 共同彙整
目前不考慮出第二篇,統整資料好累
:::
# **認識JAVA**
:::info
💡 介紹一些關於JAVA的故事及特色
:::
## Java歷史
- **Java** 是由 **James Gosling**、**Mike Sheridan** 和 **Patrick Naughton**
於 **1991 年**開發的程式語言,當時他們在 **Sun Microsystems** 工作。
- 在開發過程中,他們將 **Java** 設計為一種**跨平台**的語言,可以運行在不同的操作系統和硬體上。
- **第一版** **Java** 公開日期為 **1995 年 5 月 23 日**,當時 Java 還被稱為 **Oak**。
- **Java** 後來被 **Sun Microsystems** 正式命名為 Java,
並在 **1996年** 推出了 **Java 1.0** 版本。
- **Java** 每年都持續更新,並且由 **Oracle** 公司負責維護和開發。
- **Java 1.0** 和 **1.1** 兩個版本稱為 **Java 1**。
- **Java 1.2**、**1.3**、**1.4** 都稱為 **Java 2**,其中 **Java 2** 的最後一個版本是 **1.4.2**。
- **J2SE 5.0** 是 **Java 2** 平台的第五個版本,於 **2004** 年推出,之後改名為 **Java SE 5**。
- **Java SE 6** 於 **2006** 年推出,**Java SE 7** 於 **2011** 年推出,
**Java SE 8** 於 **2014** 年推出,**Java SE 9** 於 **2017** 年推出,
**Java SE 10** 於 **2018** 年推出,**Java SE 11** 於 **2018** 年推出,
**Java SE 12** 於 **2019** 年推出,**Java SE 13** 於 **2019** 年推出,
**Java SE 14** 於 **2020** 年推出,**Java SE 15** 於 **2020** 年推出
- **Java** 還有其他版本,例如 **Java ME(Java Micro Edition)**
和**Java EE(Java Enterprise Edition)** ,用於開發行動裝置和企業應用程式。
## **Java語言特性**
- **可攜帶性**:Java 程式會編譯成 **byte code (位元組碼)**,可以在任何安裝了 **Java Virtual Machine (JVM)** 的機器上運行,**不需要重新編譯**。
- **垃圾回收**:Java 語言提供自動回收垃圾記憶體的功能,**不需要**手動釋放記憶體。
- **物件導向**:Java 語言的設計核心是物件導向,所有的**程式都是由物件組成**,方便程式設計和維護。
- **多重繼承**:Java 語言**支援介面(interface)** 的**多重繼承**,但不支援**類(class)** 的**多重繼承**。
## **Java程式類型**
- **Java Application**:單獨運行在電腦 PC 上的 Java 程式。
- **Java Applet**:主要在 Web Page 網頁上的 Java 程式,現在已經不再被廣泛使用。
- **JavaScript**:不是 Java 程式,而是一種腳本語言,用於網頁前端開發。
- **Java Server Pages (JSP)**:在伺服器 Server 端所執行的 Java 語法的 Script 程式。
- **Android**:在 Android 作業系統執行的 Java 程式,現在已經不再使用 Java 語言,而是使用 Kotlin 或其他語言。
## **Java開發環境**
- **Java Software Development Kit (JDK)**:提供 Java 開發所需的**編譯器**、**除錯器**和**其他工具**,以及 **Java Runtime Environment (JRE)**。
- **Java Runtime Environment (JRE)**:只提供 Java 執行所需的環境,不包括**開發工具**。
## **Java平台**
Java 平台分為**三種**不同的版本:
- **Java Standard Edition (Java SE) 基本版**,適用於桌面應用程式和一些簡單的伺服器應用程式。
- **Java Enterprise Edition (Java EE) 企業版**,包含 **Servlet**、**JSP**、**Java Beans** 等,適用於大型企業應用程式。
- **Java Micro Edition (Java ME) 迷你版**,適用於嵌入式裝置和行動裝置。
## **其他關於JAVA知識**
### **物件導向**
Java 的**物件導向設計**,可以讓程式開發更容易分工與協作,
並且可以撰寫出較易讓人理解的程式碼和文件。
以下是物件導向的一些基本概念:
- **封裝 (Encapsulation)**:將屬性和方法封裝在一個類別中,只開放必要的介面給外部使用。
- **繼承 (Inheritance)**:子類別可以繼承父類別的屬性和方法,並且可以擴充或修改它們。
- **多型 (Polymorphism)**:同一個方法可以在不同的類別中有不同的實現方式。
### **大型軟體開發**
Java 的**物件導向設計**特性,適合用於**大型軟體開發**與分工。
開發人員可以將**不同的功能**模組化成**不同的類別**,並且可以透過**繼承**和**多型**等機制,
實現程式碼的重用和擴充。
---
# **類別(Class)**
:::info
Java 是一種物件導向的程式語言,使用 "**類別**" **(Class)** 來實作物件的概念。
每一個物件都是由一個類別所建立而成,這個類別定義了物件的屬性和方法。
:::
## **定義類別**
Java 中定義類別的方式如下:
```java=
public class MyClass {
// 定義類別的屬性和方法
}
```
其中,**public** 是一個存取修飾詞,表示這個類別是**公開的**,可以在其他類別中被使用。
**MyClass** 則是類別的名稱,可以自行定義。
## **程式的進入點**
### **說明**
Java 程式的進入點是 main() 函數,程式從這裡開始執行。進入點的定義如下:
```java=
public static void main(String[] args) {
// 程式開始執行的地方
}
```
- `main`:進入點的函數名稱。一定要取名為 `main`。
- ``(String[] args)``:傳遞給 `main` 的參數。所有的宣告與名稱一定要如此寫。可以是任何數量的字串參數。
- `void`:`main` 的傳回值。`void` 代表不傳回任何值。
- `public`:允許任何 class 呼叫這個 main method。
- `{}`:將您想執行的程式填在此處。每行程式後方都要以分號 `;` 分開。
---
在進入點中,可以呼叫其他方法或執行其他程式碼。
程式的執行順序是由進入點開始,往下依序執行每一行程式碼。
### **範例**
以下是一個簡單的 main 方法範例:
```java=
public class Main {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
```
在進入點中,可以呼叫其他方法或執行其他程式碼。
# **變數(Variables)**
:::info
變數是儲存資料的單位,每個變數都有各自的名稱與資料型態。
在 Java 中,變數必須先宣告才能使用。
:::
## **變數宣告(Declaration)**
變數宣告的目的是告知電腦,程式中要使用哪些變數,並配置記憶體以供存放。
變數必須在第一次使用前宣告。
變數宣告的語法如下:
```java=
DataType VarName [= Initial Value];
```
- **DataType**:變數的資料型態,例如 `int`、`double` 等。
- **VarName**:變數的名稱,可以是任何合法的識別字,建議使用有意義的名稱。
- **Initial Value**:變數的初始值,可以省略不寫。
如果省略不寫,則變數的初始值為 `0`(數值類型)或 `null`(物件類型)。
以下是一個變數宣告的範例:
```java=
int a = 24;
double b;
```
在這個範例中,我們宣告了兩個變數 `a` 和 `b`。
`a` 的資料型態為 `int`,初始值為 `24`
`b` 的資料型態為 `double`,沒有初始值。
## **變數命名規則**
在 Java 中,變數的命名規則如下:
- 變數名稱**必須**以`字母`、`底線`或`$`開頭。
- 變數名稱**不能**以`數字`開頭。
- 變數名稱**只能**包含`字母`、`數字`、`底線`或`$`。
- 變數名稱**不能**是 Java 的保留字(例如 `int`、`double` 等)。
## **資料型態**
以下這些基本資料型態是 Java 中最基本的資料型態,用來儲存各種不同的資料。
在宣告變數時,**必須**指定變數的**資料型態**。
### **整數型態**
:::info
整數型態用來儲存整數,包括`正整數`、`負整數`和`零`。
在 Java 中,整數型態包括 `byte`、`short`、`int` 和 `long` 四種。
:::
| 資料型態 | 描述 | 大小(位元組) | 範圍 |
| --- | --- | --- | --- |
| **byte** | `8` 位元的`有符號整數` | 1 | `-128` 到 `127` |
| **short** | `16` 位元的`有符號整數` | 2 | `-32,768` 到 `32,767` |
| **int** | `32` 位元的`有符號整數` | 4 |`-2,147,483,648` 到 `2,147,483,647` |
| **long** | `64` 位元的`有符號整數` | 8 | `-9,223,372,036,854,775,808` 到 `9,223,372,036,854,775,807` |
*宣告範本*
```java=
byte b = 99;
short s = 99;
int i = 99;
long l = 99L;
```
### **浮點型態**
:::info
浮點型態用來儲存浮點數,包括`正數`、`負數`和`零`。
在 Java 中,浮點型態包括 `float` 和 `double` 兩種。
:::
| 資料型態 | 描述 | 大小(位元組) | 範圍 |
| --- | --- | --- | --- |
| **float** | `單精度浮點數` | 4 | 大約 `±3.40282347E+38F`(有效位數為 `6`-`7` 位數) |
| **double** | `雙精度浮點數` | 8 | 大約 `±1.79769313486231570E+308`(有效位數為 `15` 位數) |
*宣告範本*
```java=
float f = 1.234f;
double d = 1.234;
double d = 1.234d;
```
### **字元型態**
:::info
字元型態用來儲存單個字符,包括`字母`、`數字`、`符號`和`控制字符`。
在 Java 中,字元型態為 `char`。
:::
| 資料型態 | 描述 | 大小(位元組) | 範圍 |
| --- | --- | --- | --- |
| **char** | 單個 `16` 位元的 `Unicode 字元` | 2 | `0` 到 `65,535` |
*宣告範本*
```java=
char c = 'a';
```
### **布林型態**
:::info
布林型態用來儲存布林值,只有兩種值:`true` 和 `false`。在 Java 中,
布林型態為 `boolean`。
:::
| 資料型態 | 描述 | 大小(位元組) | 範圍 |
| --- | --- | --- | --- |
| **boolean** | 僅有兩個值:`true` 或 `false` | 1 | `-` |
*宣告範本*
```java=
boolean b = true;
```
## **溢位(Overflow)**
是一種當數值超過資料型態範圍的錯誤。
在 Java 中,每種資料型態都有其範圍限制,如果資料型態無法容納某個數值,
則會發生溢位錯誤。溢位錯誤可能會導致程式產生不正確的結果,
因此在實際開發中應該避免使用可能導致溢位的操作。
以下是各種資料型態的範例程式,用來示範溢位錯誤:
```java=
// byte 溢位
byte b = 127;
b++;
System.out.println(b); // -128
// short 溢位
short s = 32767;
s++;
System.out.println(s); // -32768
// int 溢位
int i = 2147483647;
i++;
System.out.println(i); // -2147483648
// long 溢位
long l = 9223372036854775807L;
l++;
System.out.println(l); // -9223372036854775808
// float 溢位
float f = Float.MAX_VALUE;
f *= 2;
System.out.println(f); // Infinity
// double 溢位
double d = Double.MAX_VALUE;
d *= 2;
System.out.println(d); // Infinity
```
在這些範例中,我們使用了各種資料型態的最大值,然後將其加上 `1` 或乘以 `2`,以引發溢位錯誤。
當發生溢位時,資料型態的值會從最大值變成最小值,或從最小值變成最大值,因此會產生不正確的結果。
在實際開發中,我們應該避免使用可能導致溢位的操作,以確保程式的正確性。
## **常數(constant)**
在 Java 中,常數是指在程式執行過程中其值不會改變的變數。
可以使用 `final` 關鍵字來聲明一個常數。常數的語法如下:
```java=
final DataType VarName = InitialValue;
```
:::info
`DataType` 是變數的資料型別,`VarName` 是變數的名稱,`InitialValue` 是變數的初始值。
:::
---
一旦一個變數被聲明為 final,其值將不可再更改。
如果程式碼試圖更改一個 final 變數的值,將會在編譯時期產生錯誤(compile-time error)。
以下是一個常數的範例:
```java=
final double PI = 3.1415;
```
:::info
在這個範例中,`PI` 被聲明為一個 final 變數,其值為 `3.1416`。
由於 `PI` 是一個常數,所以在程式執行過程中其值不會改變。
:::
---
如果程式碼試圖更改 `PI` 的值,例如:
```java=
final double PI = 3.1415;
PI = 5.4321;
```
:::danger
則會在編譯時期產生錯誤。
:::
---
需要補充的是,Java 中的常數通常使用**全部大寫字母**表示,並使用**底線分隔單詞**,
例如 `CURRENT_USER_NUM`。
此外,常數的命名應該具有**描述性**,以便於程式碼的閱讀和理解。
# **運算子(Operator)**
:::info
運算子是在程式語言中用來執行特定操作的符號或關鍵字,
例如數學運算、邏輯運算、位元運算等。
每一種運算子都有其特定的功能和用法,並且可以應用在不同的資料型別上。
:::
## **類型**
Java 中的運算子可對一個、兩個或三個運算元執行動作。
依照所需運算元數目,運算子可分為以下**三種**:
- 一元運算子:只需要**一**個運算元,對變數進行**遞增/遞減**操作,
例如 `a++`、`--a`。
- 二元運算子:需要**兩**個運算元,將**右邊**的運算元**賦值**給**左邊**的運算元,
例如 `a = 99`。
- 三元運算子:需要**三**個運算元,語法為 `(condition) ? expression1 : expression2`,
其中 `condition` 為條件,如果條件成立,則回傳 `expression1` 的值,
否則回傳 `expression2` 的值,例如 `(a>0) ? a-1 : (a+1)`。
依照運算子擺放位置,運算子可分為以下**三種**:
- 前置運算子:運算子擺放在運算元之**前**,例如 `++i`。
- 後置運算子:運算子擺放在運算元之**後**,例如 `i++`。
- 中置運算子:運算子擺放在**中間**,例如 `a + b`。
### **算術運算子**
#### *單一運算子*
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| + | +a | 表示正 a |
| - | -a | 表示負 a |
| ! | !a | 表示邏輯非,將 a 的值取反 |
| ~ | ~a | 表示位元反轉,將 a 的二進位表示法的每個位元取反 |
| ++ | a++ 或 ++a | 表示將 a 的值加 1,若放在 a 的後面則先回傳 a 的值再加 1,若放在 a 的前面則先加 1 再回傳 a 的值 |
| -\- | a-- 或 --a | 表示將 a 的值減 1,若放在 a 的後面則先回傳 a 的值再減 1,若放在 a 的前面則先減 1 再回傳 a 的值 |
#### *二元運算子*
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| + | a + b | a 加上 b |
| - | a - b | a 減去 b |
| * | a * b | a 乘上 b |
| / | a / b | a 除以 b |
| % | a % b | a 除以 b 的餘數 |
### **指定運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| = | a = b | 將 b 的值賦給 a |
| += | a += b | 將 a 加上 b 的值後再賦給 a |
| -= | a -= b | 將 a 減去 b 的值後再賦給 a |
| \*= | a \*= b | 將 a 乘上 b 的值後再賦給 a |
| /= | a /= b | 將 a 除以 b 的值後再賦給 a |
| %= | a %= b | 將 a 除以 b 的餘數再賦給 a |
### **關係運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| == | a == b | 判斷 a 是否等於 b,若成立則回傳 true,否則回傳 false |
| != | a != b | 判斷 a 是否不等於 b,若成立則回傳 true,否則回傳 false |
| < | a < b | 判斷 a 是否小於 b,若成立則回傳 true,否則回傳 false |
| <= | a <= b | 判斷 a 是否小於等於 b,若成立則回傳 true,否則回傳 false |
| > | a > b | 判斷 a 是否大於 b,若成立則回傳 true,否則回傳 false |
| >= | a >= b | 判斷 a 是否大於等於 b,若成立則回傳 true,否則回傳 false |
### **條件運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| && | a && b | 邏輯 AND,若 a 和 b 都成立則回傳 true,否則回傳 false |
| \|\| | a \|\| b | 邏輯 OR,若 a 或 b 有一個成立則回傳 true,否則回傳 false |
### **邏輯運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| ! | !a | 表示邏輯非,將 a 的布林值取反 |
| & | a & b | 位元 AND,將 a 和 b 的二進位表示法進行 AND 運算 |
| \| | a \| b | 位元 OR,將 a 和 b 的二進位表示法進行 OR 運算 |
| ^ | a ^ b | 位元 XOR,將 a 和 b 的二進位表示法進行 XOR 運算 |
### **位元運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| << | a << b | 左位移,將 a 的二進位表示法向左移動 b 個位元 |
| >> | a >> b | 右位移,將 a 的二進位表示法向右移動 b 個位元 |
| >>> | a >>> b | 無符號右位移,將 a 的二進位表示法向右移動 b 個位元,左邊空出的位元以 0 填補 |
### **進階指定運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| &= | a &= b | 將 a 和 b 的二進位表示法進行 AND 運算後再賦給 a |
| \|= | a \|= b | 將 a 和 b 的二進位表示法進行 OR 運算後再賦給 a |
| ^= | a ^= b | 將 a 和 b 的二進位表示法進行 XOR 運算後再賦給 a |
| <<= | a <<= b | 將 a 的二進位表示法向左移動 b 個位元後再賦給 a |
| >>= | a >>= b | 將 a 的二進位表示法向右移動 b 個位元後再賦給 a |
| >>>= | a >>>= b | 將 a 的二進位表示法向右移動 b 個位元,左邊空出的位元以 0 填補後再賦給 a |
### **特殊運算子**
| 運算子 | 用法 | 說明 |
| --- | --- | --- |
| ?: | a ? b : c | 條件運算子,若 a 成立則回傳 b,否則回傳 c |
| , | a, b | 逗號運算子,先執行 a,再執行 b,最後回傳 b 的值 |
| [] | a[0] | 存取陣列元素的方式,其中 a 是一個陣列,而 [0] 表示要存取第一個元素。例如,如果 a 是 [1, 2, 3],那麼 a[0] 就是 1。 |
| . | Object.Property | 存取物件屬性的方式,其中 Object 是一個物件,而 Property 是一個屬性名稱。例如,如果有一個物件 person,其中有一個屬性 name,那麼可以使用 **person**.name 來存取這個屬性的值。 |
| (type) | (int) 3.5 | 強制轉型的方式,其中 (int) 表示要將後面的值轉型為整數型別,而 3.5 則是一個浮點數值。例如,如果要將 3.5 強制轉型為整數,那麼會得到 3。 |
| new | new Object() | 建立物件的方式,其中 new 是一個關鍵字,而 Object() 則是一個物件類別的建構函式。例如,如果有一個物件類別 Person,那麼可以使用 new Person() 來建立一個新的 Person 物件。 |
| (param, param, …) | f(X, Y, Z) | 呼叫函式的方式,其中 f 是一個函式名稱,而 X、Y 和 Z 則是傳給函式的參數。例如,如果有一個函式 add(x, y),那麼可以使用 add(2, 3) 來呼叫這個函式,並回傳 5。 |
### **運算子優先度**
|優先度| 類別 | 運算子 |
| --- | --- | --- |
| 0 | 分隔運算子 | `()` `[]` `{}` `,` `.` |
| 1 | 單一運算子 | `+` `-` `!` `~` `++` `--` |
| 2 | 指定運算子 | `=` `+=` `-=` `*=` `/=` `%=` `&=` `\|=` `^=` `<<=` `>>=` `>>>=` |
| 3 | 關係運算子 | `==` `!=` `<` `<=` `>` `>=` |
| 4 | 條件運算子 | `&&` `\|\|` |
| 5 | 位元運算子 | `&` `\|` `^` `<<` `>>` `>>>` |
# **程式區塊(Blocks)**
:::info
程式區塊是以 `{}` 大括號包覆而成,可以內含零個或以上的敘述。
通常在條件判斷語句中使用,例如 **if 判斷句**,若條件成立,就會執行 `{}` 內包含的敘述,
否則略過。在許多程式語言中,程式區塊還會配合分號 `;` 結束敘述,確保程式碼的正確執行。
:::
**範例:**
```java=
if (a > 2) {
// 如果 a 大於 2,則執行以下程式區塊內的敘述
System.out.println("a is greater than 2.");
} else {
// 如果 a 小於等於 2,則執行以下程式區塊內的敘述
System.out.println("a is less than or equal to 2.");
}
```
在程式區塊的 `{}` 內也可以包含其他的程式區塊,
例如**多層迴圈**、**巢狀**的**if 判斷**等等,只要在不同層次的程式區塊中使用不同的變數名稱,
即可避免變數名稱衝突的問題。
# **程式流程(Program-flow)**
:::info
程式可以使用結構化的方式來表達流程,讓程式碼更易讀、易維護
:::
## **循序結構**
循序結構是程式中最簡單的結構之一,它**按照順序執行敘述**,從上到下按照程式碼的順序執行,沒有任何的分支或迴圈。
```java=
int a = 1;
int b = 2;
int c = a + b;
System.out.println(c);
```
## **選擇結構**
選擇結構基於條件來決定程式的執行路徑,當條件滿足時執行 `A 敘述`,否則執行 `B 敘述`。
下面是一個簡單的 `if-else` 選擇結構的例子:
```java=
int x = 10;
if (x > 0) {
System.out.println("x 是一個正數");
} else {
System.out.println("x 不是一個正數");
}
```
## **重複結構**
重複結構可以讓程式重複執行某些敘述,以達到簡化程式碼的目的。
下面是一個簡單的 `while` 迴圈重複結構的例子:
```java=
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```
此迴圈會進行 `5` 次迴圈,每次迴圈都會把目前的數字印出來,直到迴圈次數到達 `5` 次為止。
# **基本語法(Basic)**
:::info
💡 開始寫程式囉
:::
## **if-else和switch**
`if-else` 和 `switch` 都是在程式中用來進行調條件的判斷的關鍵字。
### **if-else**
`if-else` 在判斷條件成立時執行一段程式碼,反之則執行另外一段程式碼。
```java=
if (score >= 60) {
System.out.println("pass");
} else {
System.out.println("fail");
}
```
### **switch**
`switch` 在判斷某個變數的值時,可以根據不同的值執行對應的程式碼。
```java=
switch (keyCode) {
case 37:
moveLeft();
break;
case 38:
moveUp();
break;
case 39:
moveRight();
break;
case 40:
moveDown();
break;
default:
System.out.println("invalid key");
break;
}
```
## **輸入(Input)**
:::success
在`Java`中,`Scanner`是一個用於讀取**使用者輸入**的類別。
使用`Scanner`,你可以輕鬆地從控制台讀取**使用者輸入**的資料。
:::
使用`java.util.Scanner`類別來讀取使用者從控制台輸入的資料。
創建一個`Scanner物件`,然後使用`nextInt()`方法讀取**使用者輸入**的整數。
```java=
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入一個整數:");
int num = scanner.nextInt();
System.out.println("你輸入的整數是:" + num);
scanner.close();
}
}
```
你可以使用不同的方法來讀取不同類型的輸入,
例如`nextDouble()`、`nextLine()`等。
**記得在使用完`Scanner`後關閉它,以避免資源泄漏**。
## **輸出(Output)**
:::success
在Java中,你可以使用`System.out.println()`或`System.out.print()`方法來輸出這些訊息。
:::
`System.out.println()`:會在輸出結束時自動換行
```java=
System.out.println("Hello, World!");
```
輸出結果:
```bash
Hello, World!
```
---
`System.out.print()`:方法則不會
```java=
System.out.print("Hello, ");
System.out.print("World!");
```
輸出結果:
```bash
Hello, World!
```
`System.out.println()`和`System.out.print()`方法是Java中常用的輸出方法,
它們可以幫助你將訊息輸出到控制台上,並根據需要換行或不換行。