- 簡單紀錄Java 8以下筆記
- Basic
- 數值表示不管何種進位表示,都可以透過"_"進行分隔,例如:int value = 1_0_0_0
- StringBuffer和StringBuilder有一模一樣的method,但StringBuffer有thread-safe
- Java有兩個keyword不能用,const和goto
- 迴圈
- 對array來說,for(int i = 0; i < array.length(); i++)等同for(int a : array)
- JavaBean是一種資料傳遞的結構,常用於網路
- Field必須為private
- 有getter & setter
- 可序列化
- 有一個無參數的constructor
- 繼承
- super(...)建構子
- 建構子專用
- 一定要放在子類別建構子第一行
- 呼叫父類別的建構式
- Constructor
- class如果沒有宣告任一形式的constructor,java會自動建構一個空的constructor,但只要有任一形式的constructor宣告,java就不會自動添加無參數constructor
- 子類別的constructor若沒有呼叫super(),java會自動添加super()到constructor第一行
- 若是子類別需要無參數建構子,而父類別只需要有參數建構子,這樣的情況下,程式設計師可能就會在父類別添加空的無參數建構子
- Override (覆寫)
- @Override只對method有效,對Field無效。
- 類似複寫的狀況:對於Field而言,父類別的Field會被同名的子類別Field掩蓋,因此子類別要存取父類別Field的話,要使用super.field。如果子類別的同名Field,宣告為static,仍會掩蓋父類別的同名Field,使用super.field取用field。
- 相同名稱的method,在Override時,權限存取不能小於父類別,但是子類別可以擴展父類別的存取權限
- Annotation用途
- 簡化程式碼
- 協助檢查,例如:防止人為的錯誤,@Override可以防止method name打錯
- Object相關
- hashCode()
- 實作要滿足以下特徵
- 在同一個應用程式執行期間,對同一物件呼叫 hashCode()方法,必須回傳相同的整數結果。
- 如果兩個物件使用equals(Object)測試結果為相等, 則這兩個物件呼叫hashCode()時,必須獲得相同的整數結果。
- 如果兩個物件使用equals(Object)測試結果為不相等, 則這兩個物件呼叫hashCode()時,可以獲得不同的整數結果。
- 有複寫equals()通常就需要複寫hashCode()
- 教材 4-18
- equals()實作要滿足以下特徵
- 至少實作這三項
- if (this == obj) return true;
- if (this == null) return false;
- if (!obj instance this.getClass()) return false;
- Overload (多載)
- 相同函數名稱,但參數不同 (signature不同),例如:
- foo(int a1)
- foo(int a1, int a2)
- foo(int a1, int a2, int a3)
- 使用”...”可以解決變動參數的情況
- 宣告 public void foo(int… as) {...}
- as是一種int array型態
- 若是呼叫foo(),則as相當於:int[] as = new int[0],而不會是null。
- static keyword
- 特性:
- 每個JVM裡只有一份static field/method
- 所有的object共用同一static field/method
- 使用前,會先初始化,比建構子的初始化還早
- PS: 盡量避免用private物件直接取用static field內容 (透過getter)
- static member的使用時機:
- ...
- 通常用於和OO較無關的操作,例如: java.lang.Math裡的東西
- 常見於建構子裡,進行與Object初始化相關的動作
- static initializer (blocks)
- 只要load class,就會執行
- 用於初始化static variable
- 一個class可以有多個static blocks,這些block可以出現在任何地方,執行時,則會按block出現順序執行。
- Immutable Class
- 整個物件都無法修改
- 任何的修改,只會產生出另一個物件,就如同String一樣
- 作法/要求:
- class modifier必須為final
- 所有field必須為private,且為final
- no setter methods
- 所有fields必須透過建構子初始化
- Referenc的Object必須為final,防止子類別替換內容
- 好處:
- thread-safe
- 透過減少synchronize,ap增加效能
- 可覆用性,如同String
- 若是immutable class有許多必填或選填的欄位,可以使用Builder Design Pattern產生immutable class
- Abstract
- 任何class內,只要包含任一abstract method,則必須宣告為abstract class
- abstract class無法直接new
- abstract method無需實作內容
- 大多使用interface,較少使用abstract
- final
- final fields
- 在宣告時賦予值
- 在建構子賦予值
- static + final = const value
- Nested Class
- 包含
- Inner class
- member class => 在class內的宣告
- local class => 在class/method/statement { }內的宣告
- anonymous class
- Static nested class => 在class內宣告為static的class
- 用途:
- 限制helper class的使用 => helper class指的是提供某些功能的class,但它的存在並不是整個application的主要目的
- 可以直接呼叫outer class的參數
- Enum
- 建構子必為private,因為不能直接new enum object或繼承enum class
- 常用method
- name(): String
- 用途是已知Enum,但想取得Enum的名稱字串
- valueOf(String): Enum
- 用途是已知Enum的字串名稱,但想取得Enum物件
- Interfaces
- Q: interface和abstract class的不同
- abstract class的繼承偏向具體描述的關係
- interface偏向功能性的實作
- 引入functional programming
- fuctional programming vs procedure programming
- FP是以一級函數為主的寫法,function可以是變數,參數和回傳值,傳統程序性語言的function只能是procedure,不能是其他應用
- C/C++的function pointer不是FP的概念,只是pointer的運用
- default method
- 在interface中實作預設method內容
- 有繼承效果,可被同名method @Override,即使@Override method沒有實作也可,如此便是消除default效果
- static method
- 需要實作method內容
- 不需要用default
- @FuntionalInterface
- 指的是一個interface裡只能有一個abstract method,即SAM (Single Abstract Method)
- 有其他default method, fields沒關係
- SAM的宣告可加可不加,但對Compiler有用處
- 特徵
- 類似abstract class,但只包含public和abstract methods
- 介面內宣告的field,預設為public static final
- Interface也有繼承效果,可多重繼承
- 多重繼承需要注意的地方是,不同介面的相同method,注意如下: (假設類別C實作介面A, B)
(假設介面B extends 介面A,類別C實作介面B)
- Lambda
- 一種Funtional Programming的概念 => 以函數為主的概念
- 形式: (String s) -> { … }
- WARN: 只能用在SAM
- variable reference到的lamda宣告,一樣可以取用interface內其他default method or fields
- 可用於Helper method
- 一種概念,不是Design Pattern
- 存在的目的是為了幫助某些運算,通常宣告為static method
- Stream
- 可透過Stream.of(...)建立stream
- 用of()建立的物件,建構子都是private
- 一般的Collection有兩個特別的method
- forEach()
- stream(): Stream
- Intermediate
- filter(Predicate<>())
- filter()分成好幾段和一次完成,效能差不多
- peek()
- 類似forEach(),但是元素不像forEach()會被用掉
- Map(Function<>())
- 一種處理資料的方式,處理完以後,輸出轉換後的結果
- 有MapToXXX的特定型別轉換,XXX指Int, Long, Double
- flatMap()效果和Map類似,flat意思為平坦化
- 當map處理完以後會回傳stream物件時,就可能造成Stream<Stream<XXX>>物件,如此,就需要flatMap(),將多重的Stream轉為單層Stream
- Terminal
- forEach(Cusumer<>())
- collect(), EX: stream.collect(Collections.toList())
- 從Stream轉換為Collection型態
- count(), sum(), average(), min(), max()
- Terminal short-circuit
- findFirst(), findAny(), anyMatch(), allMatch(), noneMatch()
- Optional Class
- findFirst(), findAny(), min(), max()的回傳值
- 用於包裝回傳資料的物件,包裝null避免NPE的問題
- 有OptionalDouble, OptionalInt, OptionalLong的變形
- Optional<Integer> => 宣告Optional包裝Integer
- Optional.of( 1 + 1 ) => 包裝資料
- Optional.empty => 回傳空值
- Optional.isPresent => 檢查Optional是否包裝有效資料
- Optional.ifPresent(), Optional.orElse(), Optional.
- Collectors Class
- 可搭配stream.collect()產生特定的collection,EX: Collectors.toSet()
- 執行常用的運算,EX: summingInt(), averageDouble(),
- 執行分組/合併的動作,EX:groupBy(), partitionBy(), joining()
- Collectors會自動暗示成資料本身,例如:
stream().collect(
Collectors.groupBy(
Employee::getDept,
Collectors.counting()
)
).forEach(...);
第一個Collectors代表所有資料
第二個Collectors代表分組後的資料
- Pipeline 操作
- 在一個statement內,呼叫各種method
- Method Chaining
- 類似Builder的操作
- 在過程中不會變更元素內容,只會轉換(替換)
- 操作的參數必須是Stateless
- 不能有side effect,即不能影響到不相關的變數
- stream內的elements(來自於list or array)是消耗性的,EX:經過filter()過濾以後就用掉了,forEach()就取不到了
- 每個method的操作只會在一個chain裡出現
- chain的操作可以用平行完成,EX: list.stream().parallel().forEach()
- Stream pipeline = A source + zero/more operation + terminal operation (EX: forEach())
- Lazy Operation (Deferred Execution) 特性
- 指的是在terminal operation之前,stream物件並不會真正執行中間的操作
- 可先儲存stream的操作,在需要的時候執行forEach()
- java.util.funtion package
- Predicate => 傳入T,回傳boolean,搭配filter()
- test()
- Consumer => 傳入T,回傳void,搭配forEach()
- accept()
- Function => 傳入T,回傳R,搭配Map()
- apply()
- Supplier => 無參數,回傳物件,搭配List中的add()
- get()
- 有Lazy operation效果,只有在get()的時候才會執行參數(操作)指涉的動作
- Primitive variations
- 這類用法,是為了避免primitive type轉換成reference type時,產生的autoBoxing/autoUnboxing導致的效率問題
例如:
Stream<Integer> s = Stream.of(1,2,3); // 先做三次autoBoxing
s.forEach(i -> System.out.println(i * 2)); // 三次autoUnboxing
- Stream<t>
- IntStream
- LongStream
- DoubleStream
- 沒有Byte, Short, Float, Character,因為不常用
- Consumer<> & 其他內建Functional Interface都有類似行對應
- IntConsumer
- LongConsumer
- DoubleConsumer
- 沒有Byte, Short, Float, Character,沒有對應的Stream
- Binary variations
- 原本只有一個參數,變成兩個參數
- BiConsumer<T,U>, BiPredicate<T,U>, BitFunction<T,U,R>
- Operator interface
- 簡化Function相同的泛型型態
- BinaryOperator<T> = BiFunction<T,T,T>
- UnaryOperator<T> = Function<T,T>
- Generic
- 常用關鍵字: T, E, …
- 只有List<> = List<Object>
- Class<String>並非Class<Object>的子物件
- wildcard type => "<?>"
- <>會自動推斷 => 若推斷不出來會轉成<Object>
- <?> => 無限定wildcard
- 只能get不能set,可用於宣告generic array
- <? extend XXX> => ?是XXX的子類,常用於參數回傳的型態(?)
- 使用的method以XXX為主
- <? super XXX> => ?是XXX的父類,常用於參數傳入的型態(?)
- 使用的method以XXX為主
- 已知a3 extends a2, a2 extends a1
- Set<a3>可指派給Set<? extends a1>,Set<? super a3>
- Set<a3>不能指派給Set<a1>, Set<a2>
- Set<? extends a3>不能指派給Set<? extends a1>
- Set<? extends a1>不能指派給Set<a1>
- Set<? super a3>不能指派給Set<? extends a1>
- 可見<? extends X>, <? super Y>用於泛型overloading
- Collections
- Generic不接受primitive type
- 可透過Integer, Character, Byte, Short, Long, Float, Double, Boolean的autoboxing/unboxing完成界接
- 常見method: add(), remove(), size(), isEmpty()
- Comparable & Comparator
- Collections需要排序時,會需要實作比較方法
- Comparable用於單一比較的方法,Comparator則是有不同條件的多種比較方法
- Comparable
- 實作compareTo(),比較結果回傳正數,負數和0
- Collection在排序時會自動呼叫comparaTo()
- Comparator
- 通常用於資料排序條件常變動的用途
- 實作compare(),比較結果回傳正數,負數和0
- 可搭配Collections.sort(ArrayList, Comparator),加入Comparator進行排序
- 也可運用Collection有Comparator的建構子,ex: new TreeSet<Student>(Comparator)
- Collection types
- Map
- (implement) HashMap
- (implement) HashTable
- SortedMap
- (implement) TreeMap
- String的Key按照unicode排序,即英文按照a-z,中文按照筆畫順序
- Collection
- Deque
- (implement) ArrayDeque
- 用於FIFO,LIFO等
- List
- 元素可重複,有index編號
- (implement) Arraylist
- (implement) LinkedList
- Set
- 元素不能重複且無順序性,多了get(int)
- 判斷重複與否,需要透過equals(), hashCode()進行比較
- SortedSet
- (implement) TreeSet
- 有排序功能的Set
- String的Key按照unicode排序,即英文按照a-z,中文按照筆畫順序
- (implement) Hashset
- Error Handling
- Throwable => Error & Excepetion
- Error不應用try-catch
- Unchecked Exception的特徵通常與程式本身有關,像是NPE、divided by 0,不應用try-catch預防,因為可以透過簡單的if-else排除
- Checked Exception的特徵通常與程式本身邏輯無關,像是合法的檔案名稱卻沒有檔案存在,就應當使用try-catch預防
- 錯誤的定義
- 應當是個exception,且是非預期的行為
- 可能是由於程式bug所造成
- 可能是由於程式控制以外的原因造成的
- 硬體出錯, 資料庫unreachable
- 錯誤處理,handle or declare rule
- handle原則,表示自己能夠處理這些錯誤
- declare原則,表示這些錯誤,需要其他人來處理
- Throw / Throws
- Throw是產生Exception物件,Throws是拋出Exception
- 在建構子也可能出現throws Exception
- Throws結合Closure resource,可以這樣用,
public void foo() throws IOException {
try (InputStream in = new FileInputStream(“a.txt”)) {
return in.read();
}
}
- 自訂Exception
- class XXX extends Exception => checked Exception
- class XXX extends RuntimeException => unchecked Exception
- Assertion
- 主要用於除錯程式碼
- 在Java中assert效果預設是disable
- 開啟:
- java -enableassertions MyProgram
- java -ea MyProgram
- 注意
- 避免用於檢查public method的參數
- 避免在檢查時,改變檢查的資料,Ex: assert i++ > 0;
- 用法
- assert [booleanExpression]
- 如果為false,則丟出Error
- assert [booleanExpression] : expression;
- 如果為false,執行expression,ex: assert age < 0 : “age???”;
- Date/Time API
- Old Date/Time API
- Date => 日期時間 (月份起始從0開始,時間日期混在一起)
- Calendar => 補足Date日期計算的不足
- DateFormatter => 格式化日期時間 (java.text.DateFormat)
- Java 8 補足更多日期時間計算的API,例如:不符合ISO格式、無法使用lambda、不同時區的換算較麻煩,日光節約時間
- java.time
- LocalDate, LocalTime, LocalDateTime => 時間 & 日期的處理
- Period, Duration => 計算天數 & 時數
- Instant => 機器時間,可顯示從1970.1.1到現在的秒數
- DateTimeFormatter => 格式化日期時間
- I/O
- 用完一定要close,否則GC不會回收記憶體
- 如果沒有利用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
}
}
- 可結合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
}
- 大多都繼承autoCloseable interface
- 字元I/O
- 內容通常是可顯示的文字
- Reader/Writer
- Reader.read(), Writer.write(int)
- 無buffer版
- 回傳 -1表示完成
- Reader.read(char[] buff), Writer.write(char[] buff)
- buffer版,不推薦使用
- 位元I/O
- 內容可能是一張圖
- InputStream/OutputStream
- InputStream.read(), OutputStream.write()
- 無buffer版
- 回傳-1表完成
- InputStream.read(byte[] buff), OutputStream.write(byte[] buff)
- buffer版,不推薦使用
- 包裝I/O
- 不是單純的I/O,用於包裝已有的I/O
- BufferedInputStream / BufferedReader
- BufferedReader有readLine(),這是BufferedInputStream沒有的,因為文字有換行概念
- 當BufferedXXX關閉時,包裝的I/O也會關閉,所以可以結合try-catch
- BufferedOutputStream / BufferedWriter
- 注意flush() => 之前採到的雷 QQ
- Console I/O
- InputStreamReader / OutputStreamWriter
- keyboard輸入是一種inputStream,所以讀取keyboard輸入文字需要從InputStream轉換成Reader,否則 char = 2 * byte,在轉換上會有差異
- NIO.2
- 主要物件是Path, File
- 修正原本許多效率,功能,擴展性等的問題
- 舊有API全都塞在java.io.File
- NIO將之拆分
- java.nio.file.Path => 檔案路徑相關
- java.nio.file.Files => 檔案操作
- java.nio.file.FileSystem => 檔案系統
- Path
- 產生Path物件
Path p1 = FileSystems.getDefault().getPath(“/home/file.txt”); // 適合頻繁開檔
Path p2 = Paths.get(“/home/file.txt”); // 適合不頻繁開檔
- Path API
PS. URI可用於網路存取檔案的操作,一種通用的格式
- Path是link-aware,代表symbolic-link的操作和一般檔案有些不同
- Path.normalize() => 簡化路徑,刪除多餘的 .. or .
- Path.subpath() => 取得某段路徑,類似subString
- Path.resolve() => 合併兩個路徑,類似 /home + /bin
- File API
- get() => 打開檔案,需要放在try()中自動關閉
- exists(), notExists()
- set/isReadable(), set/isWritable(), set/isExecutable(), isSameFile()
- createFile(), createDirectory(), createDirectories()
- delete(), deleteIfExists(), copy(), move()
- list() : Stream => ls, work() => tree
- lines() : Stream => 將檔案轉換成一行行的型態
- readAllLines() : ArrayList => 回傳List,可用於和舊API操作界接
- Concurrency
- 舊API在java.util.concurrent功能
- Concurrent collections
- 原有Collection,如Set, List等,並非thread-safe
- Synchronization and locking alternatives
- Thread pools
- Fixed and dynamic thread count pools available
- Parallel divide and conquer (Fork-Join)
- Thread & Runnable 常見兩種做法
- extends Thread,override run() method => 程式較簡單,較無彈性
- implement Runnable,override run() method => 較有彈性,且class的extends仍可使用
- 高階一點的API,java.util.concurrent.ExecutorService
- 概括執行緒的管理,無須手動創建,避免cpu-intensvie task等
- 使用thread pools概念
- Task可以是 Runnable or Callable
- 當task數量多於thread數量,ExecutorService會自動放入等待queue
- 建立方式
- Executors.newCachedThreadPool() => 使用cached thread pool
- Executors.newFixedThreadPool(count) => 使用固定數量的 thread pool,count建議用cpu count => Runtime.getRuntime().availableProcessors(),避免過多的cpu thread造成intensive
- 使用方式
- es.execute(Runnable) : void
- es.submit(Callable) : Future<V>
- 關閉方式
- es.shutdown() => 關閉ExecutorService,不再接收Callable
- es.awaitTermination(int duration, [time uint]) => 等待Callable回傳值
- Future
- fs.get()是blocked method,會等待future結果,因此必須完成下面任何一件事
- 確認已經submit所有項目到ExecutorService
- 準備要等待future result的該完成的程序
- 在呼叫fs.get()前,使用fs.isDone()檢查future是否完成,或使用fs.get(timeOut, timeUnit),設定等待timeout
- Shared Data
- thread-safe issue
- Atomic operation
- java.util.concurrent.atomic.*
- sychronized => 類似Lock
- 每個Java Object都有monitor,是一個可以上鎖解鎖的thread
- 放在method前,代表method本身只允許一個thread進入
- 使用 sychronized(this) {...}創建block,表示block只允許一個thread進入
- static synchronized method,是用class monitor
- Thread-safe Collection
- 將現有的Collection轉換成thread-safe型態
- java.util.Collections.synchronizedXXX( XXX ),XXX代表Set, Map, List,ex: synchronizedList(List)
- 直接創建有thread-safe型態的Collection
- Parallel Stream
- 使用
- 從Collection呼叫 => ie, list.parallelStream()
- 從Stream呼叫 => ie, list.stream().parallel()
- 從.parallel()之後的動作都是平行化的
- 使用.sequential()之後為序列化
- 注意
- Statefull stream無法平行化,因為有side effect,影響到function以外的東西
- reduce() => 將相關的function結合,若是將不相關的function結合會出錯
- .sum() 等同 .reduce(0, (a,b) -> a + b)
- (0, (sum, element) -> sum + element)
- 效能
- 關於DeadLock除錯
- run $JAVA_HOME/bin/jmc
- 點選要關注的程式,開啟threads label
- 關於亂數產生
- ThreadLocalRandom.current().nextInt() => 產生Int範圍內的亂數,相較傳統Math.random(): Double有效率
- Fork-Join Framework
- 主要是應用divide-and-conque的原理
- API
- RecursiveAction => 無回傳值的Fork-Join
- RecursiveTask<> => 有回傳值的Fork-Join
- ForkJoinPool => invoke工作 (.invoke(task))
- 用法
- extends RecursiveTask<> or RecursiveAction
- override cmpute() {...} (有固定的回傳值,類似compareTo())
- 將大的區塊divide,小的區塊conque
- 範例
- COMBINE可以是任意合併的函數
- LEFT_DATA和RIGHT_DATA指的是資料的上半或下半部
- PROCESS_DATA指的是處理資料的邏輯 (conque)
- DATA_SMALL_ENOUGH用於判斷資料的大小
- 在RecursiveAction中,回傳值的Void
- 注意事項
- 避免在I/O或blocked operation
- 單核心CPU無法透過Fork-Join加速
- 某些CPU會讓單核心執行時,效能提升,可能相對提升Fork-Join代價
- 許多問題除了單純平行化外,還有額外的代價
- 缺點
- 相較於parallel stream,Fork-Join Framework太低階了
- JDBC
- Concept
- 和Hibernate, JPA類似,他們是一種資料庫的framework,Androoid使用SQLite
- JDBC package主要是interface,由vendor提供implement,也稱為DB driver,要去各vendor網站下載driver (.jar)
- 和IO一樣需要close,也支援try-with-resource
- Connection
- URL反映資料庫的產品名稱
- jdbc:<drv>:[protocol:][db-name][;attribute=value]
- ur = “jdbc:derby://localhost:1527/EmployeeDB”;
- 其他類似“jdbc:mysql://...”,“jdbc:thin://..”
- java.sql.Connection
- DriverManager.getConnection(url, username, password)
- Operation
- java.sql.Statmemt
- Statmement stmt = con.createStatement()
- stmt.executeQuery(“SELECT * FROM xxx”) : ResultSet
- stmt.executeUpdate(sqlString) : int (受影響的rows個數)
- 需要修Table時使用,INSERT, UPDATE, DELETE or DDL(create table)
- stmt.execute(sqlString) : boolean
- 可用於各種SQL指令
- PreparedStatement
- 一般較少使用單純的Statement,雖然查詢String可透過string concat完成,但容易出現SQL injection的問題
- PreparedStatementstmt stmt = con.PreparedStatement(sqlstr)
- 可用於替換query string中,"?"的內容
- .setXXX(pos, value) => XXX是型態,pos是位置,以1開始,value是?的數值
- EX:
- "SELECT * FROM xxx WHERE salary > ?"
- 可透過.setDouble(1, 10000.0) 設定"?"為10000.0
- CallableStatement
- 可執行非SQL string,與stored procedures有關
- java.sql.ResultSet => 回傳結果型態
- 有cursor的概念,呼叫rs.next() : boolean移動cursor到下一格
- rs.getInt(“ID”), getString(“Name”) 取得欄位值
- DB的欄位編號是從1開始,和Array Index不同
- SQLException
- 取得錯誤資訊
- e.getSQLState() => 取得錯誤狀態碼
- e.getErrorCode() => 取得錯誤碼
- e.getMessage() => 取得錯誤訊息
- .getNextException()
- 取得下一個Exception
- 在SQL中Exception,有可能不只一個Exception
- Localization
- 設定檔
- Properties
- 副檔名固定.properties
- 從檔案讀取
- 從command line讀取
- ResourceBundle
- 類似property的設定檔
- 多語系慣例: [檔名]_[LangCode]_[CountryCode].properties
Locale locale = new Locale.FRANCE;
ResourceBundle.getBundle("foo", locale); // 讀取foo_fr_FR.properties
- 格式轉換
- NumberFormat
- Numberformat.getCurrencyInstance(locale)
- nf.format(numberString)
- DateTimeFormatter
- ofLocalizedXXX(FormatStyle) => XXX為Date, Time, DateTime
- withLocale(Locale) => 特定Locale的DateTimeFormatter
- Serialization
- 使用情境,例如在物件離開JVM1,要傳入JVM2時,就會需要序列化
- ClassNotFoundException在發生在JVM2,因為找不到對應的class
- 物件的關係: A includes B, C, C includes D, F
- 如果C無法進行序列化,就會出現NotSerializableException,此時,需要用讓C可以序列化
- 或是宣告C為transient
- 為了安全性的議題,避免接收者,自建一個class,此時需要SerialVersionUID
- 定義private static long serialVersionUID = ??L;
- 沒有定義時,會出現InvailidClassException
- 範例
public class Data implement Serializable {
private int id;
private transient String password;
}
- Singleton Pattern
- 使用時機在系統只需要一個這樣的物件就夠了。常用於資料庫連線的物件,或是初始化耗用資源較多的物件。
- 無法用於一次性使用的物件,例如:HttpConnection等等
- 作法/要求:
- 宣告一個private的建構子,防止外面使用
- new一個自己的物件,再宣告一個static final field指向它
- 實作一個getInstance()回傳static final field的內容
- Builder Pattern
- 當建立物件時,用到的fields很多時,就可以引入build pattern,而不是單純把所有參數塞入constructor
- 做法:
- 物件本身的無參數建構子是private,不讓外面使用,但讓內部Builder使用
- private OuterClass() {}
- 使用nested class宣告名為Builder的類別
- 加入所有outer class所需參數
- setter名稱通常是[變數名()]而非[set變數名()]
- 最後return this
- 宣告一個build()方法,回傳outer class object
- return new OuterClass();
- 範例:
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();
- 延伸閱讀
- Decorator pattern
- Factory pattern
- 補充
- Object中相關執行緒的方法
- wait() => 讓執行緒進入等待
- notify(), notifyAll() => 喚起此物件等待的 一個/所有 執行緒
- 後臺執行緒
- isDaemon()
- setDaemon(boolean) => 可標記為後台執行緒,優先緒最低
- Generic Naming
- E => Element
- K => Key
- N => Number
- T => Type
- V => Value
- S, U, V => 用於第二,三,四個型態變數
- 對Generic extends/super的限制
- 只能有一個class,或多個interface
- <T extends String & Comparable>
- Generic的擦拭
- generic不存在於JVM,會在JVM前被消除
- List<String> list = new List<>()
- 在JVM裡面,等同List<Object> list = new List<>()
- 下面等式會成立
new ArrayList<Number>().getClass() == new ArrayList<Integer>.getClass()
留言
張貼留言