# Core JAVA Note
# Ch5 繼承
1. 繼承父類語法
建構子 & 註解方式
若要調用父類別的參數可用super(…param)
若要調用父類別的方法可用super.method()
```java=
public class Employee(...){
//atttrbite
//constructor
public void getSalary(){
return this.salry;
}
}
public class Manager extends Employee{
private int bouns;
//attribute
super(attribue);
public void getSalary(){
int salary = super.getSalary();
return baseSalary + bonus;
}
}
```
2. 在一個方法的多型中,若父類為private,子類也必須為private,若宣告為final則不能再被繼承
3. 利用instanceof來確認是否可以進行型態轉換
4. 抽象使用時機:當「多個類別(Class)」之間有共同的方法(function)或屬性(attribute)時,可以將這些共用的地方寫成「抽象類別(Abstract Class)」,讓其他的「子類別(Class)」去繼承。
5. 在abstract class中盡量不要有具體方法。若需要則放在subclass or superclass。
## 5.抽象類別宣告方式
```java=
//一個關於Person基本資訊
public abstract class Person {
private String name ;
private String address;
public abstract String getDescription();
public Person(String name, String address) {
name = name;
address = address;
}
public String getName() {
return name;
}
}
```
在抽象類別中不實做,而是在擴展子類別中完成實作:
```java=
public class Student extends Person{
private String major;
public Student (String name , String major){
super(name);
this.major = major;
}
public String getDescription() {
return String.format("this major in ", major);
}
}
```
## 6.修飾子
**Private**:僅限類別內部 使用,無論是子類別、任何外部類別,都不準直接存取。
**Protected**:限同一package成員直接存取,其它package的成員,必須透過繼承的方式,才可以在子類別中存取該成員。
**Public**:可以被所有成員 存取,為最廣之存取範圍。
## 7.相等測試
在類型測試時,盡量不要用 ```instanceof```,看下例:
```java=
if(!(otherObject insanceof Employee)) return false;
```
這樣就允許otherObject屬於一個子類別。但是這樣會有一個問題:我們還是拿Employee和Mnager舉例子,我們調用```Employee.equals(Manager)``` 和```Manager.equals(Employee)``` 的結果會不一樣,這違反了Java語言規範要求equals()方法的對稱性。
* 對稱性 - 對於任何引用x和y,當且僅當y.equals(x) 返回true, x.equals(y) 也應該返回true
* 如果子類可以有自己的相等性概念,則對稱性需求將強制使用getClass檢測。
* 如果父類決定相等性概念,那麼就可以使用instanceof字符來檢測,這樣可以在不同子類的對象之間進行相等性比較
## 8.ArrayList
### ArrayList是Collection的子介面List的實作類別
* **建立 ArrayList**
```java=
ArrayList<Employee> staff = new ArrayList<Employee>();
var staff = new ArrayList<>();
```
* **加入元素 add(object o)**
```java=
staff.add(new Employee("tom", ..., ...));
```
* **陣列大小 size()**
```java=
staff.size();
```
* **取得資料 get(int index)**
```java=
Employee e = staff.get(i);
```
* **設置資料 set(int index, object o)**
```java=
staff.set(1, harry);
```
以下的Code可以使ArrayList達到靈活且容易取得內部資料:
```java=
var list = new ArrayList<>(X);
while(...){
x = ...;
list.add(x);
//利用toArray()複製a到list中
var a = new X[list.size()];
list.toArray(a);
}
```
Note:
* 不必指定ArrayList大小
* 使用```size()```而不是用length()
* 使用```a.get(i)```而不是a[i]來取得元素
## 9.Wrapper and autoboxing
Java中有兩個型態系統,**基本型態**與**類別型態** ,使用基本型態目的在於效率,然而更多時候,會使用類別建立實例,因為物件本身可以攜帶更多資訊,如果要讓基本型態像物件一樣操作,可以使用Long、Integer、Double、Float、Boolean、Byte等類別來包裹(Wrap)基本型態。
```java=
//J2SE 5.0後可以自動裝箱
//也可以自動拆箱(Auto unboxing),也就是自動取出包裹器中的基本形態資訊。例如:
Integer wrapper = 10; // 自動裝箱
int foo = wrapper; // 自動拆箱
```
## 9.進階enum
```java=
enum Size
{
SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");
private String abbreviation;
private Size(String abbreviation) { this.abbreviation = abbreviation; }
public String getAbbreviation() { return abbreviation; }
}
```
---
# Ch6 Interface lambda
## 1.Interface
* 定義屬性成員皆為常數 (即預設 public static final),因此必須給定初始值
* 定義方法時,只能為抽象方法 (即預設 public abstract,定義功能的名稱,實作部分留給相關類別 override
```java=
public interface Moveable{
public abstract void move(double x, double y )
}
```
#### Interface vs Abstract : 一個Abstract class只能繼承一次,Interface class可以拓展很多次:
```java=
public interface Power extends Moveable{
double milesPerGallon();
}
```
Java8 開始多了 default 關鍵字,可替介面加上預設實作:
```java=
public interface Compareable<T>{
default int compareTo(T other){
return 0;
}
}
```
剛剛定義了移動的介面,接下來實作出Car class
```java=
class CarMove implements Moveable{
double speed;
public CarMove(s){
this.speed = s;
}
public void move(double x, double y ){
x++;
y++;
}
}
```
## 2.Interface defult衝突
```java=
interface Person{
default String getName(){ return ;};
}
interface Name{
default String getName(){ return ;};
}
//此時若有一個class同時實作上述 interface將會產生衝突
class Student implements Person, Named{
public String getName(){return ....}
}
```
因此,可以將Code改成:
```java=
class Student implements Person, Named{
public String getName(){
return Person.super.getName();
}
}
```
## 2.Object clone
```java=
var o = new employee("john");
emplyee copy = o.clone();
copy.raisesalary(10);
```
## 3.Lambda
**將匿名函數複製給變量的簡寫方式的函數稱為 lambda 表達式。**
**Lambda表達式本身就是一個介面的實現。(將interface new 出來後,實現class)**
```java=
//一般寫法
Runnable runnbale = new Runnable() {
public void run() {
System.out.println("run me!");
}
};
//lambda寫法
Runnable runnbale = () -> System.out.println("run me!");
//利用lambda來寫function interface
//一般寫法
public static void main(String[] args)
{
ActionListener listener = new TimePrinter();
Timer t = new Timer(10000, listener);
}
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is " + new Date());
Toolkit.getDefaultToolkit().beep();
}
}
//lambda 寫法
Timer t = new Timer(1000, event ->
System.out.println("The time is " + new Date()));
t.start();
```
lamda還有方法引用,可以將println直接傳遞到建構子中
```java=
var timer = new Timer(1000,System.out::println)
```
note:
* Java lambda 類似於 Js arrow function,例:
```javascript=
var x = () => {
console.log("run me")
}
```
* lambda引述外部變數會有問題
```java=
public static void reapeatMsg(string text, int delay){
ActionListener listener = event -> {
//這樣會有併發問題
system.out.println(text)
}
}
```
## 4.內部類
使用時機:GUI開發 & 事件處理的監聽器
* 成員內部類
```java=
class Car {
private int year;
// A member inner class named Tire public
class Tire {
private double radius;
public Tire(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
} // Member inner class declaration ends here
```
## 5.Comparator interface
1.compare(Object obj1, Object obj2)
```java=
humans.sort(
(Human h1, Human h2) -> h1.getName().compareTo(h2.getName()));
```
# Ch7 異常控制
**異常控制基本精神**
* 退回到安全狀態,並讓使用者可以執行其他命令
* 保存上次的結果,並能退出
**需要考慮到的情境**
* 使用者的輸入錯誤
* 設備錯誤
* 物理限制
* 程式碼錯誤
## 異常分類
所有的異常類別都是由Throwable中的實例

1. 聲明檢查異常
```java=
public image loadImage(String s) throws IOException{
...
}
```
2. 拋出異常
```java=
String readData(Scanner in) throws EOFException{
while(...){
...
throw new EOFException();
}
}
```
3. 自建異常
```java=
public class MyException extends Exception {
private int detail;
MyException(int a) {
detail = a;
}
public String toString(int detail) {
return "MyException = " + detail;
}
}
class ExceptionDemo {
static void computer(int a ) throws MyException{
System.out.println("call compute:" + a);
if(a > 10){
throw new MyException(a);
}else {
System.out.println("all ok");
}
}
public static void main(String[] args) {
try {
computer(1);
computer(20);
} catch (MyException e) {
System.out.println("error: " + e);
}
}
}
```

4. try-catch-finally
```java=
var in = new FileInputStream(...);
try{
//1
}catch{
//2
}finally{
in.close();
}
```
5. try-with-resource
```java=
public static void main(String[] args) throws Exception {
try (MyAutoCloseable myAutoClosable = new MyAutoCloseable()) {
myAutoClosable.doIt();
}
}
public class MyAutoCloseable implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("close");
}
public void doIt() {
System.out.println("MyAutoClosable doing it!");
}
}
```
## assertion(斷言)
* 基本用於開發測試環境
```java=
//啟用assertion
java -ea:MyClass
```
## Logger
1. 基本日誌
```java=
Logger.getGlobal().info("File -> open menu item selected")
```
2. 級別
```
Logger的級別:
SEVERE 嚴重
WARNING 警告
INFO 資訊
CONFIG 配置
FINE 良好
FINER 較好
FINEST 最好
```
logger預設的級別是INFO,比INFO更低的日誌將不顯示。
Logger的預設級別定義是在安裝目錄的lib下面的logging.properties。
java.util.logging.ConsoleHandler.level = INFO
```java=
selfie = person.shootASelfie();
try {
selfie.show();
} catch (NullPointerException e) {}
```
A:
```java=
selfie = person.shootASelfie();
try {
selfie.show();
} catch (NullPointerException e) {
throw new NullPointerException("it's null pointer");;
}
```
# Ch8 泛型
## 泛型基本概念
在Java增加泛型機制之前就已經有一個ArrayList類,這個ArrayList類的泛型概念是使用繼承來實現的。
```java=
public class ArrayList {
private Object[] elementData;
public Object get(int i) {....}
public void add(Object o) {....}
}
```
這個類存在兩個問題:
當獲取一個值的時候必須進行強制類型轉換
沒有錯誤檢查,可以向陣列中添加任何類的物件
## 泛型基本寫法
```java=
//Object<ClassName> arrayListName;
ArrayList<Employee> x = new ArrayList<Employee>();
```
```java=
List<IHat> hats = new ArrayList<>();
hats.add(new Ushanka()); // that one has ear flaps
hats.add(new Fedora());
hats.add(new Sombrero());
for (IHat hat : hats) {
if (hat.hasEarFlaps()) {
hats.remove(hat);
}
}
```
```java=
public class IHat {
private int price;
private String size;
private String color;
public IHat() {
}
public int getPrice() {
return price;
}
public String getSize() {
return size;
}
public String getColor() {
return color;
}
}
```
## 定義一個簡單的泛型
```java=
public class Pair<T>{
private T first;
private T second;
public Pair(){ first == null ;second == null};
public Pair(T first , T second){ this.first = first , this.second = second; }
//getter
}
```
note:<T>:為類型變數,<E>:表示變數,<K,V>為鍵和值
可以用具體的類型來實例化:
```java=
Pair<String> x;
```
## 帶有型別參數的方法
接著,我們可以定義一個帶有型別參數的方法
而泛型方法可以在一般的class中定義,也可以在泛型中定義
```java=
class ArrayAlg{
public static <T> T getMiddle(T ...a){
return a[a.length/2];
}
}
```
當未來我們要調用此方法時,可以像這樣寫:
```java=
String middle = Array.<String>getMiddle(...)
```
## 型別變數的限定
有時候我們對型別變數會有些約束,如下程式碼會有些問題存在:
```java=
class ArrayAlg{
public static <T> T min(T[] a)
{
if( a == null ) return null;
T small = a[0];
for(int i = 1 ; i<a.length() ; a++){
if(small.compareTo(a[i])) {
small = a[i];
}
return small;
}
}
```
在上面的程式碼中,無法確定T是否有compareTo的方法
所以我們可以改寫為:
```java=
pubic static <T extends comparable> T min<T[] a>...
```
## 型別擦除
Java在編譯期間,所有的泛型資訊都會被擦掉,下列程式碼證明Java型別的型別擦除:
```java=
public class Test {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(123);
System.out.println(list1.getClass() == list2.getClass());
}
}
```
上述說明泛型型別String和Integer都被擦除掉了,只剩下原始型別。
## 泛型限制
1. 泛型型別變數不能是基本型別
```java=
//error
ArrayList<double> x = new ArrayList<double>();
```
2. 編譯時的instanceof
ArrayList<String> arrayList = new ArrayList<String>();
因為型別擦除之後,ArrayList<String>只剩下原始型別,泛型資訊String不存在了。
那麼,編譯時進行型別查詢的時候使用下面的方法是錯誤的
```java=
if( arrayList instanceof ArrayList<String>)
```
3. 無法創建型別參數的實例
```java=
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
```
但是可以這樣做:
```java=
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
```
最後這樣調用他:
```java=
List<String> ls = new ArrayList<>();
append(ls, String.class);
```
4. 不能創建參數化的陣列
```java=
var Table = new Pair<String>[10];
```
5. 不能聲明型別是型別參數的靜態字段:
```java=
public class MobileDevice<T> {
private static T os;
// ...
}
```
因為下列程式碼會造成混淆:
```java=
MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
```
6. 泛型不能直接或間接地擴展Throwable
```java=
// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ } // compile-time error
// Extends Throwable directly
class QueueFullException<T> extends Throwable { /* ... */ // compile-time error
```
但是,可以在throws 子句中使用類型參數:
```java=
class Parser<T extends Exception> {
public void parse(File file) throws T { // OK
// ...
}
}
```
## 泛型的繼承規則
若Employee與Manerger一個為class另一個為subclass,那Pair<Manerger>是Pair<Employee>的子類嗎? 答案是不是
```java=
Manerger[] top = ...;
Pair<Employee> result = ArrayAlg.minmax(top);//error
```
## 型態通配字元(Wildcard)
假設使用 GenericFoo 類別來如下宣告名稱:
```java=
GenericFoo<Integer> foo1 = null;
GenericFoo<Boolean> foo2 = null;
```
那麼名稱 foo1 就只能參考 GenericFoo<Integer> 類型的實例,而名稱 foo2 只能參考 GenericFoo<Boolean> 類型的實例,也就是說下面的方式是可行的:
```java=
foo1 = new GenericFoo<Integer>();
foo2 = new GenericFoo<Boolean>();
```
但是有這麼一個需求,foo 可以如下接受所指定的實例,讓foo可以接受兩個實例
```java=
foo = new GenericFoo<ArrayList>();
foo = new GenericFoo<LinkedList>();
```
那可以改寫成
```java=
GenericFoo<? extends List> foo = null;
foo = new GenericFoo<ArrayList>();
.....
foo = new GenericFoo<LinkedList>();
....
```
上述<? extends List> 表示型態未知,只知會是實作 List 介面的類別,屬於向上限制
除了可以向上限制,也可以向下限制,只要使用 "super" 關鍵字,例如:
```java=
GenericFoo<? super StringBuilder> foo = null;
```
foo 就只接受 StringBuilder 及其上層的父類型態,也就是只能接受 GenericFoo<StringBuilder> 與 GenericFoo<Object> 的實例。
# Ch9 Collection


## LinkedList
```java=
public class LinkedListTest
{
public static void main(String[] args)
{
List<String> a = new LinkedList<>();
a.add("Amy");
a.add("Carl");
a.add("Erica");
List<String> b = new LinkedList<>();
b.add("Bob");
b.add("Doug");
b.add("Frances");
b.add("Gloria");
// merge the words from b into a
ListIterator<String> aIter = a.listIterator();
Iterator<String> bIter = b.iterator();
while (bIter.hasNext())
{
if (aIter.hasNext()) aIter.next();
aIter.add(bIter.next());
}
System.out.println(a);
// remove every second word from b
bIter = b.iterator();
while (bIter.hasNext())
{
bIter.next(); // skip one element
if (bIter.hasNext())
{
bIter.next(); // skip next element
bIter.remove(); // remove that element
}
}
System.out.println(b);
// bulk operation: remove all words in b from a
a.removeAll(b);
System.out.println(a);
}
}
```
## Set
```java=
public class SetTest
{
public static void main(String[] args)
{
Set<String> words = new HashSet<>(); // HashSet implements Set
long totalTime = 0;
try (Scanner in = new Scanner(System.in))
{
while (in.hasNext())
{
String word = in.next();
long callTime = System.currentTimeMillis();
words.add(word);
callTime = System.currentTimeMillis() - callTime;
totalTime += callTime;
}
}
Iterator<String> iter = words.iterator();
for (int i = 1; i <= 20 && iter.hasNext(); i++)
System.out.println(iter.next());
System.out.println(". . .");
System.out.println(words.size() + " distinct words. " + totalTime + " milliseconds.");
}
}
```
## TreeSet
```java=
public class TreeSetTest
{
public static void main(String[] args)
{
SortedSet<Item> parts = new TreeSet<>();
parts.add(new Item("Toaster", 1234));
parts.add(new Item("Widget", 4562));
parts.add(new Item("Modem", 9912));
System.out.println(parts);
NavigableSet<Item> sortByDescription = new TreeSet<>(
Comparator.comparing(Item::getDescription));
sortByDescription.addAll(parts);
System.out.println(sortByDescription);
}
}
```
## Priority queue
```java=
public class PQTest
{
public static void main(String[] args)
{
PriorityQueue<LocalDate> pq = new PriorityQueue<>();
pq.add(LocalDate.of(1906, 12, 9)); // G. Hopper
pq.add(LocalDate.of(1815, 12, 10)); // A. Lovelace
pq.add(LocalDate.of(1903, 12, 3)); // J. von Neumann
pq.add(LocalDate.of(1910, 6, 22)); // K. Zuse
System.out.println("Iterating over elements...");
for (LocalDate date : pq)
System.out.println(date);
System.out.println("Removing elements...");
while (!pq.isEmpty())
System.out.println(pq.remove());
}
}
```
Result:

## Map
```java=
public class MapTest
{
public static void main(String[] args)
{
Map<String, EmployeeForMap> staff = new HashMap<>();
staff.put("144-25-5464", new EmployeeForMap("Amy Lee"));
staff.put("567-24-2546", new EmployeeForMap("Harry Hacker"));
staff.put("157-62-7935", new EmployeeForMap("Gary Cooper"));
staff.put("456-62-5527", new EmployeeForMap("Francesca Cruz"));
// print all entries
System.out.println(staff);
// remove an entry
staff.remove("567-24-2546");
// replace an entry
staff.put("456-62-5527", new EmployeeForMap("Francesca Miller"));
// look up a value
System.out.println(staff.get("157-62-7935"));
// iterate through all entries
staff.forEach((k, v) ->
System.out.println("key=" + k + ", value=" + v));
}
}
public class EmployeeForMap
{
private String name;
private double salary;
public EmployeeForMap(String name)
{
this.name = name;
salary = 0;
}
public String toString()
{
return "[name=" + name + ", salary=" + salary + "]";
}
}
```
### IdentityHashMap
```java=
public class AddingElementsToIdentityHashMap {
public static void main(String[] args)
{
// Creating an empty IdentityHashMap
Map<Integer, String> identity_hash
= new IdentityHashMap<Integer, String>();
// Mapping string values to int keys
// using put() method
identity_hash.put(10, "Geeks");
identity_hash.put(15, "4");
identity_hash.put(20, "Geeks");
identity_hash.put(25, "Welcomes");
identity_hash.put(30, "You");
// Displaying the IdentityHashMap
System.out.println("Initial Mappings are: "
+ identity_hash);
// Inserting existing key along with new value
// previous value gets returned and stored in
// returned_value
String returned_value
= (String)identity_hash.put(20, "All");
// Verifying the returned value
System.out.println("Returned value is: "
+ returned_value);
// Displaying the new map
System.out.println("New map is: " + identity_hash);
// Creating a new Identityhash map and copying
Map<Integer, String> new_Identityhash_map
= new IdentityHashMap<Integer, String>();
new_Identityhash_map.putAll(identity_hash);
// Displaying the final IdentityHashMap
System.out.println("The new map: "
+ new_Identityhash_map);
}
}
```

**HashMap 與 IdentityHashMap主要差異:**

## 排序
```java=
public class ShuffleTest
{
public static void main(String[] args)
{
List<Integer> numbers = new ArrayList<>();
for (int i = 1; i <= 49; i++)
numbers.add(i);
Collections.shuffle(numbers);
List<Integer> winningCombination = numbers.subList(0, 6);
Collections.sort(winningCombination);
System.out.println(winningCombination);
}
}
```
{"metaMigratedAt":"2023-06-16T08:43:27.714Z","metaMigratedFrom":"Content","title":"Core JAVA Note","breaks":true,"contributors":"[{\"id\":\"5ab386fa-9b07-4b0c-a740-d1ef5cf00a9a\",\"add\":21217,\"del\":1134}]"}