1080617-1080621 JavaSE 8筆記

  1. 簡單紀錄Java 8以下筆記

  1. Basic
    1. 數值表示不管何種進位表示,都可以透過"_"進行分隔,例如:int value = 1_0_0_0
    2. StringBuffer和StringBuilder有一模一樣的method,但StringBuffer有thread-safe
    3. Java有兩個keyword不能用,const和goto
    4. 迴圈
      1. 對array來說,for(int i = 0; i < array.length(); i++)等同for(int a : array)

  1. JavaBean是一種資料傳遞的結構,常用於網路
    1. Field必須為private
    2. 有getter & setter
    3. 可序列化
    4. 有一個無參數的constructor

  1. 繼承
    1. super(...)建構子
      1. 建構子專用
      2. 一定要放在子類別建構子第一行
      3. 呼叫父類別的建構式
    2. Constructor
      1. class如果沒有宣告任一形式的constructor,java會自動建構一個空的constructor,但只要有任一形式的constructor宣告,java就不會自動添加無參數constructor
      2. 子類別的constructor若沒有呼叫super(),java會自動添加super()到constructor第一行
      3. 若是子類別需要無參數建構子,而父類別只需要有參數建構子,這樣的情況下,程式設計師可能就會在父類別添加空的無參數建構子
    3. Override (覆寫)
      1. @Override只對method有效,對Field無效。
      2. 類似複寫的狀況:對於Field而言,父類別的Field會被同名的子類別Field掩蓋,因此子類別要存取父類別Field的話,要使用super.field。如果子類別的同名Field,宣告為static,仍會掩蓋父類別的同名Field,使用super.field取用field。
      3. 相同名稱的method,在Override時,權限存取不能小於父類別,但是子類別可以擴展父類別的存取權限


父類別
子類別
access
public
protected
private
public
無論有沒有@Override
都會強制繼承method
無論有沒有@Override
都會強制繼承method
private method無法繼承:
有@Override會出現錯誤
無@Override則不會錯誤,因為是新的method
protected
無論有沒有@Override
都會編譯錯誤
無論有沒有@Override
都會強制繼承method
private method無法繼承:
有@Override會出現錯誤
無@Override則不會錯誤,因為是新的method
private
無論有沒有@Override
都會編譯錯誤
無論有沒有@Override
都會編譯錯誤
private method無法繼承:
有@Override會出現錯誤
無@Override則不會錯誤,因為是新的method

  1. Annotation用途
    1. 簡化程式碼
    2. 協助檢查,例如:防止人為的錯誤,@Override可以防止method name打錯

  1. Object相關
    1. hashCode()
      1. 實作要滿足以下特徵
        1. 在同一個應用程式執行期間,對同一物件呼叫 hashCode()方法,必須回傳相同的整數結果。
        2. 如果兩個物件使用equals(Object)測試結果為相等, 則這兩個物件呼叫hashCode()時,必須獲得相同的整數結果。
        3. 如果兩個物件使用equals(Object)測試結果為不相等, 則這兩個物件呼叫hashCode()時,可以獲得不同的整數結果。
      2. 有複寫equals()通常就需要複寫hashCode()
        1. 教材 4-18
    2. equals()實作要滿足以下特徵
      1. 至少實作這三項
        1. if (this == obj) return true;
        2. if (this == null) return false;
        3. if (!obj instance this.getClass()) return false;

  1. Overload (多載)
    1. 相同函數名稱,但參數不同 (signature不同),例如:
      1. foo(int a1)
      2. foo(int a1, int a2)
      3. foo(int a1, int a2, int a3)
    2. 使用”...”可以解決變動參數的情況
      1. 宣告 public void foo(int… as) {...}
        1. as是一種int array型態
        2. 若是呼叫foo(),則as相當於:int[] as = new int[0],而不會是null。
  2. static keyword
    1. 特性:
      1. 每個JVM裡只有一份static field/method
      2. 所有的object共用同一static field/method
      3. 使用前,會先初始化,比建構子的初始化還早
      4. PS: 盡量避免用private物件直接取用static field內容 (透過getter) 
    2. static member的使用時機:
      1. ...
      2. 通常用於和OO較無關的操作,例如: java.lang.Math裡的東西
      3. 常見於建構子裡,進行與Object初始化相關的動作
    3. static initializer (blocks)
      1. 只要load class,就會執行
      2. 用於初始化static variable
      3. 一個class可以有多個static blocks,這些block可以出現在任何地方,執行時,則會按block出現順序執行。

  1. Immutable Class
    1. 整個物件都無法修改
    2. 任何的修改,只會產生出另一個物件,就如同String一樣
    3. 作法/要求:
      1. class modifier必須為final
      2. 所有field必須為private,且為final
      3. no setter methods
      4. 所有fields必須透過建構子初始化
      5. Referenc的Object必須為final,防止子類別替換內容
    4. 好處:
      1. thread-safe
      2. 透過減少synchronize,ap增加效能
      3. 可覆用性,如同String
    5. 若是immutable class有許多必填或選填的欄位,可以使用Builder Design Pattern產生immutable class

  1. Abstract
    1. 任何class內,只要包含任一abstract method,則必須宣告為abstract class
    2. abstract class無法直接new
    3. abstract method無需實作內容
    4. 大多使用interface,較少使用abstract

  1. final
    1. final fields
      1. 在宣告時賦予值
      2. 在建構子賦予值
    2. static + final = const value

  1. Nested Class
    1. 包含
      1. Inner class
        1. member class => 在class內的宣告
        2. local class => 在class/method/statement { }內的宣告
        3. anonymous class
      2. Static nested class => 在class內宣告為static的class
    2. 用途:
      1. 限制helper class的使用 => helper class指的是提供某些功能的class,但它的存在並不是整個application的主要目的
      2. 可以直接呼叫outer class的參數

  1. Enum
    1. 建構子必為private,因為不能直接new enum object或繼承enum class
    2. 常用method
      1. name(): String
        1. 用途是已知Enum,但想取得Enum的名稱字串
      2. valueOf(String): Enum
        1. 用途是已知Enum的字串名稱,但想取得Enum物件

  1. Interfaces
    1. Q: interface和abstract class的不同
      1. abstract class的繼承偏向具體描述的關係
      2. interface偏向功能性的實作
    2. 引入functional programming
      1. fuctional programming vs procedure programming
        1. FP是以一級函數為主的寫法,function可以是變數,參數和回傳值,傳統程序性語言的function只能是procedure,不能是其他應用
          1. C/C++的function pointer不是FP的概念,只是pointer的運用
    3. default method
      1. 在interface中實作預設method內容
      2. 有繼承效果,可被同名method @Override,即使@Override method沒有實作也可,如此便是消除default效果
    4. static method
      1. 需要實作method內容
      2. 不需要用default
    5. @FuntionalInterface
      1. 指的是一個interface裡只能有一個abstract method,即SAM (Single Abstract Method)
        1. 有其他default method, fields沒關係
      2. SAM的宣告可加可不加,但對Compiler有用處
    6. 特徵
      1. 類似abstract class,但只包含public和abstract methods
      2. 介面內宣告的field,預設為public static final
      3. Interface也有繼承效果,可多重繼承
        1. 多重繼承需要注意的地方是,不同介面的相同method,注意如下: (假設類別C實作介面A, B)

Class C
a.method()
b.method()

default
static
abstract
default
需實作method(),不實作會出現函數引用衝突的錯誤
不衝突,method分屬a, b,C無須實作method()
需實作method()
static
不衝突,method分屬a, b,C無須實作method()
不衝突,method分屬a, b,C無法也無須實作method()
不衝突,method分屬a, b,C必須實作method()
abstract
需實作method()
不衝突,method分屬a, b,C必須實作method()
需實作method(),不實作會出現未實作錯誤

(假設介面B extends 介面A,類別C實作介面B)
Class C
a.method()
b.method()

default
static
abstract
default
b.method覆蓋a.method,C不用實作method
不會覆蓋a.method(),C不用實作method
b.method覆蓋a.method,C不用實作method
static
不會覆蓋a.method(),C不用實作method
不會覆蓋a.method(),C不用實作method
不會覆蓋a.method(),C要實作method
abstract
b.method覆蓋a.method,C要實作method
不會覆蓋a.method(),C要實作method
b.method覆蓋a.method,C要實作method

  1. Lambda
    1. 一種Funtional Programming的概念 => 以函數為主的概念
    2. 形式: (String s) -> { … }
    3. WARN: 只能用在SAM
      1. variable reference到的lamda宣告,一樣可以取用interface內其他default method or fields
    4. 可用於Helper method
      1. 一種概念,不是Design Pattern
      2. 存在的目的是為了幫助某些運算,通常宣告為static method

  1. Stream
    1. 可透過Stream.of(...)建立stream
      1. 用of()建立的物件,建構子都是private
    2. 一般的Collection有兩個特別的method
      1. forEach()
      2. stream(): Stream
        1. Intermediate
          1. filter(Predicate<>())
            1. filter()分成好幾段和一次完成,效能差不多
          2. peek()
            1. 類似forEach(),但是元素不像forEach()會被用掉
          3. Map(Function<>())
            1.  一種處理資料的方式,處理完以後,輸出轉換後的結果
            2. 有MapToXXX的特定型別轉換,XXX指Int, Long, Double
          4. flatMap()效果和Map類似,flat意思為平坦化
            1. 當map處理完以後會回傳stream物件時,就可能造成Stream<Stream<XXX>>物件,如此,就需要flatMap(),將多重的Stream轉為單層Stream
        2. Terminal
          1. forEach(Cusumer<>())
          2. collect(), EX: stream.collect(Collections.toList())
            1. 從Stream轉換為Collection型態
          3. count(), sum(), average(), min(), max()
        3. Terminal short-circuit
          1. findFirst(), findAny(), anyMatch(), allMatch(), noneMatch()
      3. Optional Class
        1. findFirst(), findAny(), min(), max()的回傳值
        2. 用於包裝回傳資料的物件,包裝null避免NPE的問題
        3. 有OptionalDouble, OptionalInt, OptionalLong的變形
        4. Optional<Integer> => 宣告Optional包裝Integer
        5. Optional.of( 1 + 1 ) => 包裝資料
        6. Optional.empty => 回傳空值
        7. Optional.isPresent => 檢查Optional是否包裝有效資料
        8. Optional.ifPresent(), Optional.orElse(), Optional.
      4. Collectors Class
        1. 可搭配stream.collect()產生特定的collection,EX: Collectors.toSet()
        2. 執行常用的運算,EX: summingInt(), averageDouble(),
        3. 執行分組/合併的動作,EX:groupBy(), partitionBy(), joining()
        4. Collectors會自動暗示成資料本身,例如:
stream().collect(
Collectors.groupBy(
Employee::getDept,
Collectors.counting()
)
).forEach(...); 
第一個Collectors代表所有資料
第二個Collectors代表分組後的資料
    1. Pipeline 操作
      1. 在一個statement內,呼叫各種method
      1. Method Chaining
        1. 類似Builder的操作
        2. 在過程中不會變更元素內容,只會轉換(替換)
          1. 操作的參數必須是Stateless
          2. 不能有side effect,即不能影響到不相關的變數
        3. stream內的elements(來自於list or array)是消耗性的,EX:經過filter()過濾以後就用掉了,forEach()就取不到了
        4. 每個method的操作只會在一個chain裡出現
        5. chain的操作可以用平行完成,EX: list.stream().parallel().forEach()
      2. Stream pipeline = A source + zero/more operation + terminal operation (EX: forEach())
      3. Lazy Operation (Deferred Execution) 特性
        1. 指的是在terminal operation之前,stream物件並不會真正執行中間的操作
        2. 可先儲存stream的操作,在需要的時候執行forEach()
    1. java.util.funtion package
      1. Predicate => 傳入T,回傳boolean,搭配filter()
        1. test()
      2. Consumer => 傳入T,回傳void,搭配forEach()
        1. accept()
      3. Function => 傳入T,回傳R,搭配Map()
        1. apply()
      4. Supplier => 無參數,回傳物件,搭配List中的add()
        1. get()
        2. 有Lazy operation效果,只有在get()的時候才會執行參數(操作)指涉的動作
      5. Primitive variations
        1. 這類用法,是為了避免primitive type轉換成reference type時,產生的autoBoxing/autoUnboxing導致的效率問題
例如:
Stream<Integer> s = Stream.of(1,2,3); // 先做三次autoBoxing
s.forEach(i -> System.out.println(i * 2)); // 三次autoUnboxing
        1. Stream<t>
          1. IntStream
          2. LongStream
          3. DoubleStream
          4. 沒有Byte, Short, Float, Character,因為不常用
        2. Consumer<> & 其他內建Functional Interface都有類似行對應
          1. IntConsumer
          2. LongConsumer
          3. DoubleConsumer
          4. 沒有Byte, Short, Float, Character,沒有對應的Stream
      1. Binary variations
        1. 原本只有一個參數,變成兩個參數
        2. BiConsumer<T,U>, BiPredicate<T,U>, BitFunction<T,U,R>
        3. Operator interface
          1. 簡化Function相同的泛型型態
          2. BinaryOperator<T> = BiFunction<T,T,T>
          3. UnaryOperator<T> = Function<T,T>
  1. Generic
    1. 常用關鍵字: T, E, …
    2. 只有List<> = List<Object>
    3. Class<String>並非Class<Object>的子物件
    4. wildcard type => "<?>"
      1. <>會自動推斷 => 若推斷不出來會轉成<Object>
      2. <?> => 無限定wildcard
        1. 只能get不能set,可用於宣告generic array
      3. <? extend XXX> => ?是XXX的子類,常用於參數回傳的型態(?)
        1. 使用的method以XXX為主
      4. <? super XXX> => ?是XXX的父類,常用於參數傳入的型態(?)
        1. 使用的method以XXX為主
      5. 已知a3 extends a2, a2 extends a1
        1. Set<a3>可指派給Set<? extends a1>,Set<? super a3>
        2. Set<a3>不能指派給Set<a1>, Set<a2>
        3. Set<? extends a3>不能指派給Set<? extends a1>
        4. Set<? extends a1>不能指派給Set<a1>
        5. Set<? super a3>不能指派給Set<? extends a1>
        6. 可見<? extends X>, <? super Y>用於泛型overloading

  1. Collections
    1. Generic不接受primitive type
      1. 可透過Integer, Character, Byte, Short, Long, Float, Double, Boolean的autoboxing/unboxing完成界接
    2. 常見method: add(), remove(), size(), isEmpty()
    3. Comparable & Comparator
      1. Collections需要排序時,會需要實作比較方法
      2. Comparable用於單一比較的方法,Comparator則是有不同條件的多種比較方法
      3. Comparable
        1. 實作compareTo(),比較結果回傳正數,負數和0
        2. Collection在排序時會自動呼叫comparaTo()
      4. Comparator
        1. 通常用於資料排序條件常變動的用途
        2. 實作compare(),比較結果回傳正數,負數和0
        3. 可搭配Collections.sort(ArrayList, Comparator),加入Comparator進行排序
        4. 也可運用Collection有Comparator的建構子,ex: new TreeSet<Student>(Comparator)
    4. Collection types
      1. Map
        1. (implement) HashMap
        2. (implement) HashTable
        3. SortedMap
          1. (implement) TreeMap
          2. String的Key按照unicode排序,即英文按照a-z,中文按照筆畫順序
      2. Collection
        1. Deque
          1. (implement) ArrayDeque
            1. 用於FIFO,LIFO等
        2. List
          1. 元素可重複,有index編號
          2. (implement) Arraylist
          3. (implement) LinkedList
        3. Set
          1. 元素不能重複且無順序性,多了get(int)
          2. 判斷重複與否,需要透過equals(), hashCode()進行比較
          3. SortedSet
            1. (implement) TreeSet
            2. 有排序功能的Set
            3. String的Key按照unicode排序,即英文按照a-z,中文按照筆畫順序
          4. (implement) Hashset

  1. Error Handling
    1. Throwable => Error & Excepetion
      1. Error不應用try-catch
      2. Unchecked Exception的特徵通常與程式本身有關,像是NPE、divided by 0,不應用try-catch預防,因為可以透過簡單的if-else排除
      3. Checked Exception的特徵通常與程式本身邏輯無關,像是合法的檔案名稱卻沒有檔案存在,就應當使用try-catch預防
    2. 錯誤的定義
      1. 應當是個exception,且是非預期的行為
      2. 可能是由於程式bug所造成
      3. 可能是由於程式控制以外的原因造成的
        1. 硬體出錯, 資料庫unreachable
    3. 錯誤處理,handle or declare rule
      1. handle原則,表示自己能夠處理這些錯誤
      2. declare原則,表示這些錯誤,需要其他人來處理
    4. Throw / Throws
      1. Throw是產生Exception物件,Throws是拋出Exception
      2. 在建構子也可能出現throws Exception
      3. Throws結合Closure resource,可以這樣用,
public void foo() throws IOException {
try (InputStream in = new FileInputStream(“a.txt”)) {
return in.read();
}
}
    1. 自訂Exception
      1. class XXX extends Exception => checked Exception
      2. class XXX extends RuntimeException => unchecked Exception

  1. Assertion
    1. 主要用於除錯程式碼
      1. 在Java中assert效果預設是disable
      2. 開啟:
        1. java -enableassertions MyProgram
        2. java -ea MyProgram
    2. 注意
      1. 避免用於檢查public method的參數
      2. 避免在檢查時,改變檢查的資料,Ex: assert i++ > 0;
    3. 用法
      1. assert [booleanExpression]
        1. 如果為false,則丟出Error
      2. assert [booleanExpression] : expression;
        1. 如果為false,執行expression,ex: assert age < 0 : “age???”;

  1. Date/Time API
    1. Old Date/Time API
      1. Date => 日期時間 (月份起始從0開始,時間日期混在一起)
      2. Calendar => 補足Date日期計算的不足
      3. DateFormatter => 格式化日期時間 (java.text.DateFormat)
    2. Java 8 補足更多日期時間計算的API,例如:不符合ISO格式、無法使用lambda、不同時區的換算較麻煩,日光節約時間
      1. java.time
        1. LocalDate, LocalTime, LocalDateTime => 時間 & 日期的處理
        2. Period, Duration => 計算天數 & 時數
        3. Instant => 機器時間,可顯示從1970.1.1到現在的秒數
        4. DateTimeFormatter => 格式化日期時間

  1. I/O
    1. 用完一定要close,否則GC不會回收記憶體
      1. 如果沒有利用try-catch的auto-close,則有很多細節需要注意
InputStream fs = null;
try {
fs = new InputStream(“...”); // throw Exceptions
int s = fs.read(); // throw IOException

// fs.close(); // bad
} catch (IOException e) {
// deal with failure of fs.read()
} finally {
try {
fs.close();
} catch(Exception e) {
// deal with fs NPE
}
}
      1. 可結合try-catch中自動關閉Stream
try (fs = new InputStream(“...”); // throw Exceptions) {
fs.read();  // throw IOException
} catch (IOException e) {
// deal with failure of fs.read()
} catch (Exception e) {
// deal with fs NPE
}
      1. 大多都繼承autoCloseable interface
    1. 字元I/O
      1. 內容通常是可顯示的文字
      2. Reader/Writer
        1. Reader.read(), Writer.write(int)
          1. 無buffer版
          2. 回傳 -1表示完成
        2. Reader.read(char[] buff), Writer.write(char[] buff)
          1. buffer版,不推薦使用
    2. 位元I/O
      1. 內容可能是一張圖
      2. InputStream/OutputStream
        1. InputStream.read(), OutputStream.write()
          1. 無buffer版
          2. 回傳-1表完成
        2. InputStream.read(byte[] buff), OutputStream.write(byte[] buff)
          1. buffer版,不推薦使用
    3. 包裝I/O
      1. 不是單純的I/O,用於包裝已有的I/O
      2. BufferedInputStream / BufferedReader
        1. BufferedReader有readLine(),這是BufferedInputStream沒有的,因為文字有換行概念
      3. 當BufferedXXX關閉時,包裝的I/O也會關閉,所以可以結合try-catch
      4. BufferedOutputStream / BufferedWriter
        1. 注意flush() => 之前採到的雷 QQ
    4. Console I/O
      1. InputStreamReader / OutputStreamWriter
        1. keyboard輸入是一種inputStream,所以讀取keyboard輸入文字需要從InputStream轉換成Reader,否則 char = 2 * byte,在轉換上會有差異
    5. NIO.2
      1. 主要物件是Path, File
      2. 修正原本許多效率,功能,擴展性等的問題
        1. 舊有API全都塞在java.io.File
        2. NIO將之拆分
          1. java.nio.file.Path => 檔案路徑相關
          2. java.nio.file.Files => 檔案操作
          3. java.nio.file.FileSystem => 檔案系統
      3. Path
        1. 產生Path物件
Path p1 = FileSystems.getDefault().getPath(“/home/file.txt”); // 適合頻繁開檔
Path p2 = Paths.get(“/home/file.txt”); // 適合不頻繁開檔
        1. Path API
PS. URI可用於網路存取檔案的操作,一種通用的格式
          1. Path是link-aware,代表symbolic-link的操作和一般檔案有些不同
          2. Path.normalize() => 簡化路徑,刪除多餘的 .. or .
          3. Path.subpath() => 取得某段路徑,類似subString
          4. Path.resolve() => 合併兩個路徑,類似 /home + /bin
        1. File API
          1. get() => 打開檔案,需要放在try()中自動關閉
          2. exists(), notExists()
          3. set/isReadable(), set/isWritable(), set/isExecutable(), isSameFile()
          4. createFile(), createDirectory(), createDirectories()
          5. delete(), deleteIfExists(), copy(), move()
          6. list() : Stream => ls, work() => tree
          7. lines() : Stream => 將檔案轉換成一行行的型態
          8. readAllLines() : ArrayList => 回傳List,可用於和舊API操作界接
  1. Concurrency
    1. 舊API在java.util.concurrent功能
      1. Concurrent collections
        1. 原有Collection,如Set, List等,並非thread-safe
      2. Synchronization and locking alternatives
      3. Thread pools
        1. Fixed and dynamic thread count pools available
        2. Parallel divide and conquer (Fork-Join)
    2. Thread & Runnable 常見兩種做法
      1. extends Thread,override run() method => 程式較簡單,較無彈性
      2. implement Runnable,override run() method => 較有彈性,且class的extends仍可使用
    3. 高階一點的API,java.util.concurrent.ExecutorService
      1. 概括執行緒的管理,無須手動創建,避免cpu-intensvie task等
      2. 使用thread pools概念
      3. Task可以是 Runnable or Callable
      4. 當task數量多於thread數量,ExecutorService會自動放入等待queue
      5. 建立方式
        1. Executors.newCachedThreadPool() => 使用cached thread pool
        2. Executors.newFixedThreadPool(count) => 使用固定數量的 thread pool,count建議用cpu count => Runtime.getRuntime().availableProcessors(),避免過多的cpu thread造成intensive
      6. 使用方式
        1. es.execute(Runnable) : void
        2. es.submit(Callable) : Future<V>
      7. 關閉方式
        1. es.shutdown() => 關閉ExecutorService,不再接收Callable
        2. es.awaitTermination(int duration, [time uint]) => 等待Callable回傳值
      8. Future
        1. fs.get()是blocked method,會等待future結果,因此必須完成下面任何一件事
          1. 確認已經submit所有項目到ExecutorService
          2. 準備要等待future result的該完成的程序
          3. 在呼叫fs.get()前,使用fs.isDone()檢查future是否完成,或使用fs.get(timeOut, timeUnit),設定等待timeout
    1. Shared Data
      1. thread-safe issue
      2. Atomic operation
        1. java.util.concurrent.atomic.*
      3. sychronized => 類似Lock
        1. 每個Java Object都有monitor,是一個可以上鎖解鎖的thread
        2. 放在method前,代表method本身只允許一個thread進入
        3. 使用 sychronized(this) {...}創建block,表示block只允許一個thread進入
        4. static synchronized method,是用class monitor
    2. Thread-safe Collection
      1. 將現有的Collection轉換成thread-safe型態
        1. java.util.Collections.synchronizedXXX( XXX ),XXX代表Set, Map, List,ex: synchronizedList(List)
      2. 直接創建有thread-safe型態的Collection
    1. Parallel Stream
      1. 使用
        1. 從Collection呼叫 => ie, list.parallelStream()
        2. 從Stream呼叫 => ie, list.stream().parallel()
          1. 從.parallel()之後的動作都是平行化的
          2. 使用.sequential()之後為序列化
      2. 注意
        1. Statefull stream無法平行化,因為有side effect,影響到function以外的東西

      3. reduce() => 將相關的function結合,若是將不相關的function結合會出錯
        1. .sum() 等同 .reduce(0, (a,b) -> a + b)
          1. (0, (sum, element) -> sum + element)
      1. 效能

    1. 關於DeadLock除錯
      1. run $JAVA_HOME/bin/jmc
      2. 點選要關注的程式,開啟threads label
    2. 關於亂數產生
      1. ThreadLocalRandom.current().nextInt() => 產生Int範圍內的亂數,相較傳統Math.random(): Double有效率

  1. Fork-Join Framework
    1. 主要是應用divide-and-conque的原理
    2. API
        1. RecursiveAction => 無回傳值的Fork-Join
        2. RecursiveTask<> => 有回傳值的Fork-Join
        3. ForkJoinPool => invoke工作 (.invoke(task))
    3. 用法
      1. extends RecursiveTask<> or RecursiveAction 
      2. override cmpute() {...} (有固定的回傳值,類似compareTo())
        1. 將大的區塊divide,小的區塊conque
      3. 範例
        1. COMBINE可以是任意合併的函數
        2. LEFT_DATA和RIGHT_DATA指的是資料的上半或下半部
        3. PROCESS_DATA指的是處理資料的邏輯 (conque)
        4. DATA_SMALL_ENOUGH用於判斷資料的大小
        5. 在RecursiveAction中,回傳值的Void
    1. 注意事項
      1. 避免在I/O或blocked operation
      2. 單核心CPU無法透過Fork-Join加速
      3. 某些CPU會讓單核心執行時,效能提升,可能相對提升Fork-Join代價
      4. 許多問題除了單純平行化外,還有額外的代價
    2. 缺點
      1. 相較於parallel stream,Fork-Join Framework太低階了

  1. JDBC
    1. Concept
      1. 和Hibernate, JPA類似,他們是一種資料庫的framework,Androoid使用SQLite
      2. JDBC package主要是interface,由vendor提供implement,也稱為DB driver,要去各vendor網站下載driver (.jar)
      3. 和IO一樣需要close,也支援try-with-resource
    2. Connection
      1. URL反映資料庫的產品名稱
        1. jdbc:<drv>:[protocol:][db-name][;attribute=value]
        2. ur = “jdbc:derby://localhost:1527/EmployeeDB”;
        3. 其他類似“jdbc:mysql://...”,“jdbc:thin://..”
      2. java.sql.Connection
        1. DriverManager.getConnection(url, username, password)
    3. Operation
      1. java.sql.Statmemt
        1. Statmement stmt = con.createStatement()
        2. stmt.executeQuery(“SELECT * FROM xxx”) : ResultSet
        3. stmt.executeUpdate(sqlString) : int (受影響的rows個數)
          1. 需要修Table時使用,INSERT, UPDATE, DELETE or DDL(create table)
        4. stmt.execute(sqlString) : boolean
          1. 可用於各種SQL指令
      2. PreparedStatement
        1. 一般較少使用單純的Statement,雖然查詢String可透過string concat完成,但容易出現SQL injection的問題
        2. PreparedStatementstmt stmt = con.PreparedStatement(sqlstr)
        3. 可用於替換query string中,"?"的內容
          1. .setXXX(pos, value)  => XXX是型態,pos是位置,以1開始,value是?的數值
        4. EX:
          1. "SELECT * FROM xxx WHERE salary > ?"
          2. 可透過.setDouble(1, 10000.0) 設定"?"為10000.0
      3. CallableStatement
        1. 可執行非SQL string,與stored procedures有關
      1. java.sql.ResultSet => 回傳結果型態
        1. 有cursor的概念,呼叫rs.next() : boolean移動cursor到下一格
        2. rs.getInt(“ID”), getString(“Name”) 取得欄位值
        3. DB的欄位編號是從1開始,和Array Index不同
    1. SQLException
      1. 取得錯誤資訊
        1. e.getSQLState() => 取得錯誤狀態碼
        2. e.getErrorCode() => 取得錯誤碼
        3. e.getMessage() => 取得錯誤訊息
      2. .getNextException()
        1. 取得下一個Exception
        2. 在SQL中Exception,有可能不只一個Exception

  1. Localization
    1. 設定檔
      1. Properties
        1. 副檔名固定.properties
        2. 從檔案讀取
        1. 從command line讀取
      1. ResourceBundle
        1. 類似property的設定檔
        2. 多語系慣例: [檔名]_[LangCode]_[CountryCode].properties
Locale locale = new Locale.FRANCE;
ResourceBundle.getBundle("foo", locale); // 讀取foo_fr_FR.properties
    1. 格式轉換
      1. NumberFormat
        1. Numberformat.getCurrencyInstance(locale)
        2. nf.format(numberString)
      2. DateTimeFormatter
        1. ofLocalizedXXX(FormatStyle) => XXX為Date, Time, DateTime
        2. withLocale(Locale) => 特定Locale的DateTimeFormatter

  1. Serialization
    1. 使用情境,例如在物件離開JVM1,要傳入JVM2時,就會需要序列化
      1. ClassNotFoundException在發生在JVM2,因為找不到對應的class
    2. 物件的關係: A includes B, C, C includes D, F
      1. 如果C無法進行序列化,就會出現NotSerializableException,此時,需要用讓C可以序列化
      2. 或是宣告C為transient
    3. 為了安全性的議題,避免接收者,自建一個class,此時需要SerialVersionUID
      1. 定義private static long serialVersionUID = ??L;
        1. 沒有定義時,會出現InvailidClassException
    4. 範例
public class Data implement Serializable {
private int id;
private transient String password;
}

  1. Singleton Pattern
    1. 使用時機在系統只需要一個這樣的物件就夠了。常用於資料庫連線的物件,或是初始化耗用資源較多的物件。
    2. 無法用於一次性使用的物件,例如:HttpConnection等等
    3. 作法/要求:
      1. 宣告一個private的建構子,防止外面使用
      2. new一個自己的物件,再宣告一個static final field指向它
      3. 實作一個getInstance()回傳static final field的內容

  1. Builder Pattern
    1. 當建立物件時,用到的fields很多時,就可以引入build pattern,而不是單純把所有參數塞入constructor
    2. 做法:
      1. 物件本身的無參數建構子是private,不讓外面使用,但讓內部Builder使用
        1. private OuterClass() {}
      2. 使用nested class宣告名為Builder的類別
        1. 加入所有outer class所需參數
        2. setter名稱通常是[變數名()]而非[set變數名()]
          1. 最後return this
        3. 宣告一個build()方法,回傳outer class object
          1. return new OuterClass();
    3. 範例:
public class OuterClass {
int a, b, c, d, e, f, g, h, i;
private OuterClass(Builder builder) {
a = builder.a;
...
}
public static class Builder {
int a, b, c, d, e, f, g, h, i;
public OuterClass.Builder static a(int a) {...}
public OuterClass build() {
return new OutClass(this);
}
}
}

OuterClass obj = new OuterClass.Builder()
.a(a).b(b).build();

  1. 延伸閱讀
    1. Decorator pattern
    2. Factory pattern

  1. 補充
    1. Object中相關執行緒的方法
      1. wait() => 讓執行緒進入等待
      2. notify(), notifyAll() => 喚起此物件等待的 一個/所有 執行緒
    2. 後臺執行緒
      1. isDaemon()
      2. setDaemon(boolean) => 可標記為後台執行緒,優先緒最低
    3. Generic Naming
      1. E => Element
      2. K => Key
      3. N => Number
      4. T => Type
      5. V => Value
      6. S, U, V => 用於第二,三,四個型態變數
    4. 對Generic extends/super的限制
      1. 只能有一個class,或多個interface
      2. <T extends String & Comparable>
    5. Generic的擦拭
      1. generic不存在於JVM,會在JVM前被消除
        1. List<String> list = new List<>()
        2. 在JVM裡面,等同List<Object> list = new List<>()

      2. 下面等式會成立
new ArrayList<Number>().getClass() == new ArrayList<Integer>.getClass()

留言