# Java
###### tags: `software` `開發`
[Spring Boot](/jhcHVQ4uT9WdieYtprPQdQ)
## 1. Java Terms
`Java` OOP語言、Exception處理框架、自動GC、JVM移植能力、隱藏指標、網路應用起家
`JavaBean` 只是一種**符合特殊規範的class**
`SpringBean` 由Spring管的**JavaBean**
`Spring` 一種擁有**IoC/AOP**特性的框架
`JDBC` 一種API,用來**連接DB**、執行SQL
`ApplicationContext` 載入configuration (使Spring可以開始管beans)
`JRE` `JDK` JRE提供跑Java程式**運行需要的環境**; JDK除了提供環境,還提供**開發工具**
`OOP` 繼承、封裝、多型 (**泡麵範例**)
`Spring IoC Container` 就是ApplicationContext
`public` `protected` `無` `private` **存取權限層級**從 同project>僅子類>同package>僅getter/setter
`JPA` 一套基於ORM的規範
`final` 太監,要初始化雞雞,然後無法被extend/implement
`static` 讓成員從『一般物件成員』變成『類別成員』
`enum` 一組常數(constants)
`package` used to group related classes
## Terms details
### `enum`
Enums are often used in `switch`
```java
enum Level {
LOW,
MEDIUM,
HIGH
}
```
```java
public class Main {
public static void main(String[] args) {
Level myVar = Level.MEDIUM;
switch(myVar) {
case LOW:
System.out.println("Low level");
break;
case MEDIUM:
System.out.println("Medium level");
break;
case HIGH:
System.out.println("High level");
break;
}
}
}
```
### `static`
/static跟non-static的差異?載入記憶體的時機。
/程式剛載入還沒執行的時候,static的方法已經載入記憶體且隨時可以被呼叫
/而一般變數的成員(non-static)還沒被初始化,還沒在記憶體中佔有空間,直白一點說就是根本還不存在。
#### when to use it?
> 如果您正在編寫實用程序類並且它們不應該被更改。
> 如果該方法沒有使用任何實例變量。
> 如果任何操作不依賴於實例創建。
> 如果有一些代碼可以很容易地被所有實例方法共享,則將該代碼提取到靜態方法中。
> 如果您確定方法的定義永遠不會被更改或覆蓋。因為靜態方法不能被覆蓋。
> ex1. call new Util().method(arg) -> Util.method(arg) or method(arg)
> ex2. :您確實希望 String 類有一個 removeSpecialChars() method 但他不存在,那你可以創建一個xxxUtil class 並調用 removeSpecialChars(s) 而不是 s.removeSpecialChars()
```java=
package com.dbs.ccd.util;
import java.util.*;
public class CollectionUtil {
public static String appendStringWithoutDuplicateAsc(String oriCommaSeparatedString, String newInputString) {
List<String> strList = Arrays.asList(oriCommaSeparatedString.split(","));
Set<String> strSet = new HashSet<>(strList);
strSet.add(newInputString);
// Ascending order
Set<String> sortedDisclaimerTermSet = new TreeSet<String>(strSet);
// from Set to Comma Separated String
String newCommaSeparatedString = String.join(",", sortedDisclaimerTermSet);
return newCommaSeparatedString;
}
}
```
```java=
import static com.dbs.ccd.util.CollectionUtil.appendStringWithoutDuplicateAsc;
public class xxxController {
String newDisclaimersTerm
= appendStringWithoutDuplicateAsc(disclimerTermOri, reqBody.getDisclaimerTerm());
}
```

### `JavaBean`
只是一種`規範`(只要符合規範的class,就可以稱它為JavaBean)
> 規範有3項:
> 1. 使用`getters/setters` methods (所以屬性都要設為`private`)
> 2. 一個`public`的no-argument constructor
> 3. Implements Serializable (非序列化物件就不成儲存狀態)
```java
@Entity
public class Employee implements Serializable{
@Id
private int id;
private String name;
private int salary;
public Employee() {}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
//name, salary 略...
}
```
---
### `SpringBean`
即JavaBean,只是由 Spring IoC Container 來管理。
___
### `JPA`
[ref: Spring Data JPA - Reference Documentation](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation)

即Java持久化api,是**一種基於ORM的規範**。
它和創建Java 類一樣簡單,沒有任何的約束和限制,只需要使用 javax.persistence.Entity進行註釋 @Entity
```java?line_numbers=false
@Entity /*指定當前類是持久化實體類*/
class Employee {
}
```
**持久化**
通常是指將易丟失的**數據傳輸到不易丟失的介質上**,從而實現數據的長期保存。
**ORM**
對象關係映射。主要實現**對象到關係數據庫數據的映射**。當實現一個應用程序時(不使用O/R Mapping),我們可能會寫特別多數據訪問層的代碼(CRUD),而這些代碼都是**餘冗的**。而使用ORM則會大大**減少重複性代碼**。
常見的 ORM 框架:Mybatis、Hibernate、JPA
JPA和Hibernate的關係就像JDBC和JDBC驅動的關係,JPA是規範,Hibernate除了作爲ORM框架之外,它也是一種JPA實現。
**常用註解說明**
* @Entity :指定當前類是持久化實體類,不能省略
* @Table
* 作用:指定實體類和表之間的對應關係,可以省略
* 默認:表名=類名(省略後)
* 屬性: name:指定數據庫表的名稱
* @Id :指定當前字段是主鍵。不能省略
* @GeneratedValue
* 作用:指定主鍵的生成方式。。
* 屬性: strategy :指定主鍵生成策略。
* @Column
* 作用:指定實體類屬性和數據庫表之間的對應關係
---
### `JDBC`
一種API,用來連接DB、執行SQL
下載JDBC Driver jar + import 即可使用
___
### `ApplicationContext`
載入configuration (使Spring可以開始管beans)
```java
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println(applicationContext.getDisplayName());
System.out.println(applicationContext.getId());
MyBean myBean = applicationContext.getBean(MyBean.class);
System.out.println(myBean.getApplicationId());
}
}
```
___
### `JRE` `JDK`
* JRE(Java Runtime Enviroment) 是 Java 的运行环境。面向 Java 程序的使用者,而不是开发者。如果你仅下载并安装了 JRE,那么你的系统只能运行 Java 程序。JRE 是运行 Java 程序所必须环境的集合,包含 JVM 标准实现及 Java 核心类库。它不包含开发工具(编译器、调试器等)。
* JDK(Java Development Kit) 又称 J2SDK(Java2 Software Development Kit),是 Java 开发工具包,它提供了 Java 的开发环境(提供了编译器 javac 等工具
---
### `Java`語言特性
[ref](https://caterpillar.gitbooks.io/javase6tutorial/content/c1_2.html)
* 1.物件導向的(Object-oriented)
可以讓您設計出可重用的元件,或者是直接使用別人所撰寫好的 Java 元件,並使開發出來的軟體更具彈性且容易維護。
* 2.堅固的
相較於C++,沒有了指標(Pointer),程式比較不會崩掉。
* 3.安全的
1.多了自動垃圾回收(GC),不用擔心資源回收問題;
2.有Exception處理架構,讓開發人員可以掌握程式中各種突發的例外狀況。(也有synchronized同步鎖、final等處理機制)
```java
public void doAction(......) {
try {
xxx.doBusiness();
} catch(Exception e) {
return false;
}
}
```
* 4.網路的(Network-savvy)
Java本身就是由網路誕生的,許多功能與應用都與網路相關,例如,WebSocket, JSP/Servlet。
* 5.易移植性的
有JVM(Java Virtual Machine),就可以在任何系統上運行Java程式。
---
### 修飾子 `public` `protected` `無` `private`
public - 任何人都可以存取 (**project**內的任何人)
protected - 僅該**子類**可存取(保護孩子)
(no modifier,預設) - **package**權限 (同package內的,都可存取)
private - 僅讓人用**getter/setter**存取
權限大小: public > protected > (no modifier) > private
```java?line_numbers=false
public int value = 1;
protected int value = 2;
int value = 3;
private int value = 4;
```
| | 同一類別 | 同套件 | 不同套件的子類 | 不同套件且非子類 |
| ---------------- |:--------:|:------:|:--------------:|:----------------:|
| **public** | ● | ● | ● | ● |
| **protected** | ● | ● | ● | |
| **(no modifer)** | ● | ● | | |
| **private** | ● | | | |
---
### 補充:面向過程 vs 面向對象

#### 概念
* 他們都是解決實際問題的一種**思想**,不該局限於語言,彼此也不相對。解決複雜問題,宏觀上,可以透過面向對象將事物之間**複雜關係拆解、分類**;但具體到**微觀操作**上,我們仍使用面向流程
* **面向過程**(線性思維),求的是**效能和速度** (因此C適合,因為它是系統級別語言);
**面向對象**(抽象化思惟),求的是解決**軟體結構**難題 (C++,Java適合,因為有封裝/繼承/多型)
#### 優缺
* 面向過程-優點:較高性能(因面向對象需要實例化,會耗能)。因此單片機mcu開發、硬體圖形渲染、算法封裝適合應用於此
* 面向過程-缺點:復用性低、**維護難**、難以多線程
* 面向對象-優點:易復用、易維護(可讀性高、低耦合)、易擴展
* 面向對象-缺點:程序處理效率較低、碰到瓶頸可能就要重構
#### 面向對象優點範例
見上圖大象笑話,面向對象具下列優點
1. 現實映射:面向對象更符合計算機對客觀世界的映射。冰箱、大象都是現實中存在的對象
2. 易復用:如果換成要把河馬放進冰箱,只要添加一個河馬類,然後復用原來的冰箱,即可快速實現
3. 低耦合:冰箱、大象、冷笑話系統分別實現自己的功能,對外僅提供接口,把實現封裝到內部
#### QA
* 問題:有沒有意識到自己是在面向對象還是在面向過程
## 2. 物件導向元素 — 封裝、繼承、多型
「物件導向」(object-oriented)總是會提供及:物件、抽象、封裝、繼承、多型
* 封裝(Encapsulation):醬包跟麵的工作都在泡麵工廠做完了,我們 **只要拿來泡就好**
* 繼承(Inheritance):我們可以買了泡麵之後,再自己 **加蛋加料**
* 多型(Polymorphism):一樣是泡麵,**實作**出來的口味都不一樣 (我們只要先定義泡麵裡面要有麵、醬料包、湯調味包就好,至於**哪種麵、醬、湯,先不要寫明**)
### 封裝
一個class的定義,我們稱之為「封裝」,封裝的目的之一是定義物件的「介面」(interface),另一個目的在於隱藏操作的細節
開發者可以將一個class封裝,讓它變成JAR檔(也就是Library)工人使用。
```java
pulic class Light {
private int _brightness;
public void on() {}
public void off() {}
public void adjustBrightness() {}
//get set 方法
}
```
### 繼承
```java
pulic class ColorLight extends Light {
// 新的操作
public void changleColor() {}
}
```
### 多型
* **#抽象類別 #延展性佳**
* 斜線代表抽象類別、抽象方法

* 多型可透過 **「介面」或「抽象類別」** 實現(抽象類是對一類**事物的抽象**,接口是對**方法的抽象**)
最有可能碰到的例子就是資料庫連線。例如說,我們可以讓 MySqlDBConnect 和 MongoDBConnect 都繼承 DBConnect,但各自保有對應不同資料庫的實作。如果一來,DBConnect 就獲得了用不同方法連線到不同資料庫的擴展,得到了對應狀況靈活使用的彈性。同時,使用 DBConnect 物件的其他物件也可以不用管現在的 DBConnect 連線是哪個子類別來工作的,只要知道能夠連線並取得資料就好,也達到了以封裝降低耦合的要求。
#### 多型example
Ref:https://www.youtube.com/watch?v=FkgLc5gFPAU&ab_channel=%E6%B0%B4%E7%90%83%E6%BD%98

##### 未使用多型
> 1. **#擴展性差** #可讀性差 #維護性差
> 2. 擴展性差:若要多加一隻狐狸、一隻猩猩呢?>要改很多地方程式碼,且容易動到原有程式碼
> 3. Class: Animal, Main
```java
//直接定義**具體**類別"動物"
public class Animal {
public static final int CAT=0;
public static final int DOG=1;
**public static final int FOX=2;**
private String name;
private int type;
public Animal(String name, int type) {
this.name = name;
this.type = type;
}
public String getName() { return name; };
public String setName() { return name; };
public String getType() { return type; };
public String setType() { return type; };
}
```
```java
public class Main{
public static void main(String[] argv){
//實作貓、狗類別(未用多型方法)
Aniaml[] animals = new Animal[]{
new Animal("貓",Animal.CAT), new Animal("狗",Animal.DOG), **new Animal("狐狸",Animal.FOX)** };
for (Animal animal : animals) {
System.out.print(animal.getName() + ":");
**switch (animal.getType()){**
case Animal.CAT:
System.out.println("喵喵");
break;
case Animal.DOG:
System.out.println("汪汪");
break;
**case Animal.FOX:
System.out.println("狐狸叫");
break; **
}
}
}
}
```
> 貓:喵喵
> 狗:汪汪
> 狐狸:狐狸叫
##### 使用多型
> 1. **#擴展性佳** #可讀性佳 #維護性佳
> 2. Class: **Cat,Dog,Fox, (abstract)Animal**, Main
```java
//定義抽象類別"動物"
public **abstract** class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
//抽象方法:就是不具體寫出方法要做甚麼,只寫出有這個方法而已
//動物會說話,但沒寫會怎麼說話
public abstract void talk();
//動物會吃飯,但沒寫會怎麼吃飯
public abstract void eat();
//動物會交配,但沒寫會怎麼交配
public abstract void mating(Animal animal);
}
```
```java
//要擴展動物聊天室(加一支新的物種"狐狸")
public class Fox extends Animal{
public Fox(String name){
super(name);
}
@Override
public void talk(){
//寫出"狐狸"具體如何說話
System.out.print("狐狸叫");
};
@Override
public void eat(){
//寫出"狐狸"具體如何吃飯
System.out.print("雜食");
};
@Override
public void mating(Animal animal){
//寫出"狐狸"具體如何交配
};
}
```
```java?line_numbers=false
public class Main{
public static void main(String[] argv){
//實作貓、狗類別(用多型方法)
Aniaml[] animals = new Animal[]{ new Cat("貓"), new Dog("狗"), **new Fox("狐狸")** };
for (Animal animal : animals) {
System.out.print(animal.getName() + ":");
animal.talk();
}
}
}
```
> 貓:喵喵
> 狗:汪汪
> 狐狸:狐狸叫
#### 多型example2

Step1.建立
* Player抽象類別、AI抽象類別;
* Human實體類別、奇/偶AI實體類別;
* 終極密碼實體類別;

Player

HumanPlayer

AI

EvenAI

GuessGame

Main

Result:

## 3. 框架:Spring, SpringMVC, SpringBoot
### Spring
Spring是J2EE(企業級Java)最流行的開發框架。
目的:解決企業應用開發的複雜性
功能:使用基本的JavaBean代替EJB,並提供了更多的企業應用功能
Spring是一個輕量級控制反轉(IoC)和面向切面(AOP)的容器框架。
spring框架解決了程式設計師在Java開發中長期存在的兩個痛點,那就是bean管理和統一切面,而spring的IOC和AOP恰好解決了這兩個問題。
### SpringMVC
實現最高效的web開發
### SpringBoot
Spring framework is something that we need to **manually change almost all configurations**, while Spring Boot **already provides us with zero or limited configuration standalone applications**.

## Java
### 載入jar
Buile Path完產生至libraryReference底下才算有載入

### 記憶體洩漏
如果是局部變量 離開作用域 就自然消失 不必設null 成員變量 作用域為整個類體內 設null為上策
LinkedList用完最好要clear(); StringBuilder用完最好setLength(0);
每次某個物件A不用之後,就讓它 s1=null; s2=null;
### 其他
* **運行jar時加入JVM參數**
Syntax: java [Options] -jar [jarfile] [Command Line Arguments]
Example: java **-Xms256m -Xmx512m** -jar filename.jar
> -Xms256m = 設定初始化堆記憶體大小為256MB,預設為0
> -Xmx512m = 設定JVM最大可用記憶體空間為512MB,預設為256MB
* **指定外部設定檔:**
直接讀取input參數(arg[0])
* **取得當前工作目錄:**
```
String WorkDir = System.getProperty("user.dir"));
```
* **指定log4j.properties目錄:**

* **取得file所在目錄:**
```
logger.logInfo(configFile.toString().substring(0, configFile.toString().lastIndexOf(File.separator)));
```
* Log4j -logError
如果用 logError的方法,那只是由"INFO"變ERROR。

### 常見面試題
[Java] 程式從原始碼到執行?
:::spoiler ans

```
.java
-(JDK中javac編譯)->
.class
-(JVM)->
機器可執行二進制
```
```
開發
1.開發環境開發、除錯 (Eclipse)
2.把專案打包成jar或war
3.放入web容器 (Tomcat, JBoss)
```
:::
___
[Java] static vs final?
:::spoiler ans
```
> static: 省記憶體空間
static variable:所有引用都會指向這一個地址而不會重新分配記憶體
static method:虛擬機器優先載入
static class:可以直接通過類來呼叫而不需new
```
```
class Student{
int rollno;
String name;
static String college="NTUST";
}
```
:::
___
[Java] Abstract class vs Interface?
Abstract class
> 像 **汽車骨架**
> **提供部分或完全抽象** (彈性擁有abstract或non-abstract的資料成員或方法)
> 只能 *extend* **一個抽象類**
:::info
* 不可直接實例化,**需先被繼承**
* **可以有方法本體**,也可以只定義方法原型
* 若有abstract method,繼承時**必須實作抽象方法**
:::
Interface
> 像 **週邊附加系統** (GPS/音響附加/空調)
> 僅提供 **完全抽象** (只能擁有abstract資料成員或方法)
> 可以 implements **多個介面**
:::info
* 內部變數不管如何宣告,編譯後 **皆是public static final**
* 只能定義方法原型,**不能有方法本體**
* 只要implements了,每個**方法都要實作**
:::
**Abstract Example**
```java
abstract class Bell{
protected String sound;
Bell(){
this.sound = "ting";
}
//Abstract Method
abstract public void ring();
//Non-Abstract Methods
public void increaseVolume(){
System.out.println("Increasing Volume");
}
public void decreaseVolume(){
System.out.println("Decreasing Volume");
}
}
```
```java?line_numbers=false
class SchoolBell extends Bell{
@Override
public void ring(){
System.out.println("Ringing the School bell: " + sound);
}
}
```
```java
class ChruchBell extends Bell{
@Override
public void ring(){
System.out.println("Ringing the Chruch bell: " + sound);
}
}
```
```java?line_numbers=false
public class AbstractClassDemo{
public static void main(String[] args){
SchoolBell sb = new SchoolBell();
ChruchBell cb = new ChruchBell();
//Using the overridden methods
sb.ring();
cb.ring();
//Using the non-abstract methods of Bell class
sb.increaseVolume();
cb.decreaseVolume();
}
}
/* output:
* Ringing the School bell: ting
* Ringing the Chruch Bell: ting
* Increasing Volume
* Decreasing Volume
* /
```
**Interface Example**
相較於Abstract Class不強制全部實現(不強制的method),Interface要求強制實現increaseVolume,decreaseVolume,不論是否需要
```java?line_numbers=false
interface Bell{
String sound = "ting";
//only abstract methods allowed in interface
public void ring();
public void increaseVolume();
public void decreaseVolume();
}
```
```java?line_numbers=false
class SchoolBell implements Bell{
public void ring(){
System.out.println("Ringing the School bell: " + sound);
}
@Override
public void increaseVolume(){
System.out.println("Increasing Volume of School Bell");
}
@Override
public void decreaseVolume(){
System.out.println("Decreasing Volume of School Bell");
}
}
```
```java?line_numbers=false
class ChruchBell implements Bell{
public void ring(){
System.out.println("Ringing the Chruch bell: " + sound);
}
@Override
public void increaseVolume(){
System.out.println("Increasing Volume of Chruch Bell");
}
@Override
public void decreaseVolume(){
System.out.println("Decreasing Volume of Chruch Bell");
}
}
```
```java?line_numbers=false
public class InterfaceDemo{
public static void main(String[] args){
SchoolBell sb = new SchoolBell();
ChruchBell cb = new ChruchBell();
//Using the overridden methods
sb.ring();
cb.ring();
sb.increaseVolume();
cb.decreaseVolume();
}
}
/* output:
* Ringing the School bell: ting
* Ringing the Chruch Bell: ting
* Increasing Volume of School Bell
* Decreasing Volume of Chruch Bell
* /
```
___
[Java] multiple inheritance
:::spoiler ans
```
Java don't support it:
class Test extends Parent1, Parent2
Java do support:
class TestClass implements PI1, PI2
```
:::
___
[Java] HashMap vs HashTable
| | HashMap | HashTable |
| -------- | -------- | -------- |
| 同步(執行序安全) | 不同步(不安全) | 同步(安全) |
| Null keys-values | 允許 | 不允許 |
| 效能 | 快 | 慢 |
| 應用場景 | 單執行序 | 多執行序 |
```
ConcurrentHashMap 為進階版: 高效、安全
```
___
[Java] pass-by-value vs pass-by-reference?
```
Java is pass-by-value
```
___
[Java] Int vs Integer
```
Integer 比較占記憶體
```
___
[Java] Constructor?
`
A Java constructor is special method that is called when an object is instantiated.
`
```java
class Employee {
private int id;
private String name;
private int salary;
public Employee() {}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
}
```
```java
Employee employee = new Employee();
//or
Employee employee = new Employee("Sean",40000);
```
`
___
[Java] JDK和JRE和JVM的區別?
```
Java Dev Kit;
Java Runtime Environment;
Java Virtual Machine
```
___
[Java] 異常處理機制? Error、Exception差別?
```
用物件導向的方式,把異常**封裝到 java.lang.Throwable類** 裡
```
```
> Exception: 可預料狀況 (ioException), 可用catch處理
> Error:正常情況下不會發生 (OutOfMemoryError / StackOverflowError)"
```
___
[Java] a=a+b與a+=b有什麼區別嗎?
```
> a+=b 有自動型別轉換; a=a+b沒有
byte a = 127;
byte b = 127;
b = a + b; // 報編譯錯誤:cannot convert from int to byte
b += a;
```
## Java 8
### [Lambda](https://hackmd.io/5hsgTEd_QbiFwyIvDqTzFA)
___
### Streams API
> 用以在**Collections** 中做 **批量數據操作**(篩選、排序等)

[ref](https://www.runoob.com/java/java8-streams.html)
#### Intro
* 將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。
* 元素流在管道中經過中間操作(intermediate operation)的處理,最後由最終操作(terminal operation)得到前面處理的結果。
#### 優點
* Pipelining , 可以增加效率
#### Stream Operation
* **數據源** 流的來源。可以是集合,數組,I/O channel, 產生器generator 等。
* **聚合操作** 類似SQL語句一樣的操作, 比如filter, map, reduce, find, match, sorted等。
#### Streams Vs Collections
* Stream does not store elements
* Stream is functional in nature
* The elements of a stream are only visited once
* Parallelizable
### Type Annotations
> Type Annotations tell analyzers what to look for.
#### Lists of Type Annotations
@NonNull – The compiler can determine cases where a code path might receive a null value, without ever having to debug a NullPointerException.
@ReadOnly – The compiler will flag any attempt to change the object. This is similar to Collections.unmodifiableList, but more general and verified at compile time.
@Regex – Provides compile-time verification that a String intended to be used as a regular expression is a properly formatted regular expression.
@Tainted and @Untainted – Identity types of data that should not be used together, such as remote user input being used in system commands, or sensitive information in log streams.
@m – Units of measure ensures that numbers used for measuring objects are used and compared correctly, or have undergone the proper unit conversion.
#### Examples
@NonNull List<String> A non-null list of Strings.
List<@NonNull String> A list of non-null Strings.
@Regex String validation = "(Java|JDK) [7,8]" Compile time validation that this String is a valid regular expression.