# Java 8 筆記 ###### 作者: TYT ###### tags: `Java` ## 物件變數在儲存空間的配置 ```mermaid graph TB subgraph 儲存空間; Global; Stack; Heap; end ``` - Global (全域資料) - 使用static宣告物件變數(稱「靜態變數」或「類變數」)的儲存空間 - 不同物件實體中,相同的靜態物件變數因指向相同的儲存位置,其值會互相干擾 :::spoiler 範例 ```java public class Demo { static int a = 1; int b = 2; public static void main(String[] args) { Demo d1 = new Demo(); d1.a = 10; d1.b = 20; System.out.println("d1.a: " + d1.a); System.out.println("d1.b: " + d1.b; System.out.println("----------"); Demo d2 = new Demo(); System.out.println("d2.a: " + d2.a); System.out.println("d2.b: " + d2.b); } } // 輸出: // d1.a: 10 // d1.b: 20 // --------- // d2.a: 10 // d2.b: 2 ``` ::: - Stack (堆疊) - 宣告物件變數屬於基本型態時,例如char, int等,皆儲存於Stack儲存空間 - 不同物件變數,即使值相同,亦配置於不同的位置 - 占用記憶體空間小,存取速度快 - Heap (堆積) - 宣告變數屬於參考資料型態(非基本型態)時,例如String, List等,物件變數參考值(資料來源位址)儲存於Stack,資料實體(資料本身)儲存於Heap - 不同的物件變數,其值相同時,會指向相同的Heap位置,故其值會互相干擾 ## 新功能in Java 8 - ::語法 - 使方法(method)與匿名函數(lambda)像第一類物件的使用 :::spoiler 範例: 列出隱藏檔案 ```java // 一般使用 File[] hiddenFiles = new File(".").listFiles(new FileFilter() { public boolean accept (File file){ // 過濾隱藏檔案 return file.isHidden(); } }) // 像第一類物件般的使用 File[] hiddenFiles = new File(".").listFiles(File::isHidden); ``` ::: - Predicate。抽象方法介面(functional interface) - test方法,實際參數符合Predicate,return true, 否則false :::spoiler 範例 ```java public static void main(String[] args){ Predicate<Integer> predicate = new Predicate<Integer>() { public boolean test(Integer integer){ if (integer > 5) return true; else return false; System.out.println(predicate.test(3)); // false System.out.println(predicate.test(6)); // true } ``` ::: - ->語法,匿名函式(lambda) - 適合一次性使用且簡單的方法 :::spoiler 範例 ```java List<Integer> list = Arrays.asList(3, 1, 4, 5, 2); // 一般方法 list.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } }); // 匿名函式 list.sort((o1, o2) -> o1.compareTo(o2)); ``` ::: - stream() - 簡化需要多個迭代(迴圈)的運算,以及可多核心執行,加速效率 :::spoiler 範例 ```java List<String> list = Arrays.asList("a1", "a2", "b1", "c2", "c1"); // 一般方法 List<String> list2 = new ArrayList<String>(); for (String s1 : list) { if (s1.startsWith("a")) { list2.add(s1); } } list2.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); for (String s2 : list2) { System.out.println(s2); } // stream() list.stream().filter(s1 -> s1.startsWith("a")).sorted().forEach(s2 -> System.out.println(s2)); //輸出: // a1 // a2 ``` ::: - parallelStream() - 與stream()相似,但可進行平行運算,將Stream分成多個Stream並同時執行 :::spoiler 範例 ```java List<Integer> list = Arrays.asList(1, 3, 2, 4, 5); // stream() List<Integer> greaterThan3List = list.stream().filter(i -> i > 3).collect(Collectors.toList()); // parallelStream() List<Integer> greaterThan3List = list.parallelStream().filter(i -> i > 3).collect(Collectors.toList()); ``` ::: - <a id='行為參數化'>行為參數化(bahavior parameterization)</a> - 方法做為參數傳入另一個方法,使主要方法可藉由行為參數實現不同的功能,即[策略模式](#策略模式) - 缺點: 可能會導致過多class的產生 :::spoiler 範例 ```java public class Demo { public static void main(String[] args) { List<Apple> redAndHeavyApples = filter(inventory, new RedAndHeavyPredicate()); // 紅蘋果且重量大於150的清單 List<Apple> greenAndLightApples = filter(inventory, new GreenAndLightPredicate()); // 綠蘋果且重量小於150的清單 } public List<Apple> filter(List<Apple> inventory, ApplePredicate p){ // ApplePredicate p -> 行為參數化 List<Apple> result = new ArrayList<>(); for (Apple apple : inventory){ if (p.test(apple){ result.add(apple); } } } } // 紅蘋果且重量大於150 public static class RedAndHeavyPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "red".equals(apple.getColor()) && apple.getWeight() > 150; } } // 綠蘋果且重量小於150的清單 public static class GreenAndLightPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "green".equals(apple.getColor()) && apple.getWeight() < 150; } } public interface ApplePredicate{ boolean test(Apple apple); } ``` ::: - 匿名class - 與匿名函式類似,適合一次性使用的class,但容易造成程式碼冗長且不好閱讀 - 與[行為參數化](#行為參數化)的範例對照,節省創建RedAndHeavyPredicate及GreenAndLightPredicate class :::spoiler 範例 ```java List<Apple> redApples = filterApples(invetory, new ApplePredicate(){ public boolean test(Apple a){ return "red".equals(a.getColor()); } }) ``` ::: ## 設計模式 - <a id='策略模式'>策略模式</a> - 依據不同的場景,藉由替換介面中的實體方法,達到不同的行為實現,範例如[行為參數化](#行為參數化) ## 名詞解釋 - First-class object - 第一類物件,又稱First-class citizen, First-class values, First-class entity - 為一實體(entity),支持其他實體的一般性操作,可做為參數傳遞給方法、方法的return值、及儲存於Heap的儲存空間 - Second-class value - 第二類物件,Second-class citizen, Second-class values, Second-class entity - 為一實體,可做為參數傳遞,但不能做為方法的return值及被分配給變數 - varible - 變數。 - ``` int var = 1;```中的```var```即為變數 - parameter - 形式參數,又稱formal parameter。定義方法時,給定需傳入的變數 - ``` public void ping(int param) { //TODO } ``` 中的```param```即為形式參數 - argument - 實際參數,又稱actual parameter。使用方法時,所傳入的變數 - ```ping(pong);```中的```pong```即為實際參數 ## 主要參考資料 1. 蔡文龍、何嘉益、張志成、張力元。2019。Java SE 12基礎必修課。碁峰資訊股份有限公司。臺北。 2. Java 8 in Action: Lambdas, streams, and functional-style programming. 2014. R.-G. Urma, M. Fusco, and A. Mycroft. Manning Publications. NewYork. 3. Oracle and/or its affiliates. 1993, 2022. https://docs.oracle.com/javase/8/docs/api/overview-summary.html. Oracle and/or its affiliates. ## 版本 | 時間 | 項目 | | --- | --- | | 220327 | 新增物件變數在儲存空間的配置 | | 220328 | 新增名詞解釋-First-class values | | 220329 | 新增名詞解釋-Second-class value <br> 新增功能in Java 8-::語法、Predicate.test方法 | | 220330 | 新增名詞解釋,variable, parameter, argument | | 220331 | 新增功能in Java 8-\->語法 | | 220401 | 新增功能in Java 8-stream() | | 220403 | 新增功能in Java 8-parallelStream() | | 220409 | 新增功能in Java 8-行為參數化、設計模式-策略模式 | | 220414 | 新增功能in Java 8-匿名class |