➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Java 開發筆記(四)Java 開發筆記(二)

Java 開發筆記(三)

Continued from previous post:
Java 開發筆記(二)

Table of contents

3 Java 基礎知識

3.1 關於 Java

3.1.1 Compiled language

Java 係一隻 object-oriented programming (OOP) 程式語言,需要 JVM 黎運行。
Java 需要 compilation 過程,由 Java code(.java 檔) compile 成 bytecode(.class 檔), 然後選擇性地用 JAR 或 WAR 黎再 zip 起多個 .class 檔以及 project resources。
當 Java code compile 左成 bytecode,係可以反向 decompile 返做 Java code,但唔會原汁原味,因為 compiler 有時會優化代碼, 所以 decompilers(非官方既工具)好難估到本身係點寫。另外,如果我地係寫 Java API 畀其他人用(通常係高手先會寫), 可以打包埋 sources 同 Javadoc,方便其他 developers 理解我地寫左既 code。
比較之下,JavaScript 就係一隻 scripting language,不需要 compile,如果冇 IDE,要到運行果一刻先知有冇寫錯。 JS 需要一個 enable 左 JS 既瀏覽器,或者 JS runtime environment(如 NodeJS)。
IDE 會幫我地做呢個 compilation 過程,當我地改左 code 但錯 syntax,IDE 會「鬧」我地寫錯野。 當我地 Ctrl+S 去 save 一個 Java type,IDE 都會 trigger compilation。
如果我地用 Maven 做 dependency management(方便我地用 3rd party libraries 同做版本管理)既話,當我地改左 pom.xml 然後 save, IDE 都會幫我地 build 過個 project,包括 compile code。
當我地用部分 JDK 內建既 classes,或者所有 3rd party libraries,都需要 import 先可以用到,否則連 compile 都唔成功。

3.1.2 特殊既 main method

public static void main(String[] args) {} 係一個特殊既 method,係用黎做程底既入口。 每個 class 都可以有一個 main method,所以每個 Java project 都可以有 N 個入口。 但係一般都唔會寫多過一個。除非需要唔同既入口,否則只需要一個 main method。 當我地 build 個 project 成一個 JAR(.jar 檔),我地需要提供 Main-Class 資訊。
如果用 Maven,可以喺 Maven project 既 pom.xml 裡面設置。如果用左 Spring 既 build plugin,Main-Class 既 config 係可以省略。

3.1.3 Compile time 及 runtime

Java 有 compile time 同 runtime。
  • Compile time:你寫緊 code,compiler compile 你啲 code 既時候
  • Runtime:個程式 deploy 左,run 緊既時候

3.1.4 如何 deploy Java apps

一般而言,Java apps 可以分為以下幾類:
類別格式main描述
Java API.jar畀其他相關既 projects 去 import,為左重用代碼或者高級 developers 提供 API 畀世人享用,如 Apache Commons Lang3
於 background 直接執行.jar可以 Command Prompt、Task Scheduler、cron 等 callers 去 call 個 Java app 去做啲 background tasks,只能通過 console 或 log files 見到個程式做左啲咩(前提係要 developers 有 code 到個 app 會 print log messages)
可直接執行既 GUI.jar會顯示 GUI(圖形使用者介面),Java GUI 技術有 Swing、SWT、JavaFX
Web application.jar .war需要 deploy 去一個 web container,如 Apache Tomcat、 Eclipse Jetty、JBoss WildFly、IBM WebSphere Application Server。呢個做法較舊派
可直接執行既 web application.jar如 Spring Boot,因為已經內嵌左一個 Tomcat container,係一個可以直接用 Java Runtime Environment(JRE)運行既 web app。呢個做法係新主流
我地唔會拎住成抽 bytecode .class 檔去 deploy,但會將佢地連埋 manifest(一啲 metadata)打包成 .jar.war 檔。其實本質上都係一個 .zip 格式。
如果用緊 Eclipse,我地可以喺 Eclipse 度行。直接撳個 launch 掣去 run as Java application 就得。
如果係可執行既 Java apps,唔想喺 Eclipse 度面行,可以 build/export 左做 JAR 先,然後打 command 黎執行:
java -jar My-Application-1.0.jar
如果係 Spring Boot app 而且用左 Maven,可以打 command 等 Maven 幫我地 call JDK 去 compile 然後執行:
mvn spring-boot:run
註:當我地個 pom.xml 用左 spring-boot-maven-plugin 呢個 Maven build plugin 既時候,個 Maven project 就會多左一個 run goal。
JAR 檔其實都係 ZIP:

3.2 Modifiers 修飾符

用於:
  • Type
  • Class/instance variable
  • Constructor
  • Method
  • Local variable
  • Constructor/method parameter
註:如果用錯左 modifiers,compiler 會話你知。

3.2.1 Access modifiers

Modifier常用程度作用
public所有 classes 都用得呢樣野
protected只有 exactly 同一個 package 既所有 classes(但唔包括 subpackages)或者所有 subclasses 先用得呢樣野
乜都唔打,即係 default access modifier只有 exactly 同一個 package 既所有 classes 先用得呢樣野(但唔包括 subpackages)
private只有呢個 class 先用得呢樣野
註:
  • 將所有野用曬 public 係一定 work,但係會令 access 太濫,影響 code maintenance,因為你唔知邊啲野係要 expose 畀其他 classes 用,所以最好係 limit access,最有限既 access 夠做就用果個。

3.2.2 Non-access modifiers

Modifier常用程度作用
static當呢樣野屬於 class(所有 object copies 都 share 一樣既)而唔係 instance(唔同既 object copies 會有唔同)
final當一個 class 唔可以被 subclass;當一個 method 唔可以被 override;當一個 variable 只可以並且必須 assign 一次 value(assign null 都算)
abstract當一個 class 既 methods 唔齊全;當一個 method 冇 method body
default喺 interface 裡面可以 declare 一啲有 method body(implementation)既 methods
synchronized多線程編程會用到
transientJDK 自帶既 serialization 功能會用到,但不影響 3rd party library 如 Jackson Databind 既 serialization
volatile多線程編程會用到
native當一個 method 係以 Java Native Interface(JNI)呼叫底層 code

3.2.3 Modifiers 既例子

1public class Foo { // type: public 2 private static final String MESSAGE = "Hello World"; // class variable: private static final 3 4 private final String name; // instance variable: private final 5 6 public Foo(final String name) { // constructor: public; constructor parameter: final 7 this.name = name; 8 } 9 10 public String sayHi() { // method: public 11 final String message = MESSAGE; // local variable: final 12 return toLowerCase(message); 13 } 14 15 public String sayHi(final String message) { // method: public; method parameter: final 16 return toLowerCase(message); 17 } 18 19 private String toLowerCase(String str) { // method: private 20 return str==null ? "" : str.toLowerCase(); 21 } 22}

3.3 Classes / types

Java 有 primitive types 同 object types(classes)。所有 primitive types 都有對應既 wrapper object types。

3.3.1 Primitive data types 原始數據類型

Primitive types:
  • boolean (true / false)
  • int(自然數)
  • long(自然數,正負數範圍比 int 大)
  • float(有小數點)
  • double(有小數點,,正負數範圍比 float 大)
  • byte(較少用)
  • char(單字/符號,幾乎唔需要用到)
以上都唔係 object。

3.3.2 Primitive data type conversion/casting

Primitive data types 之間可以轉換(conversion/casting),但要注意每隻 data type 既 value 上下限,同埋留意轉換過程可唔可以保留精確度。
喺需要處理金額之類需要百分百精確度既情境,一律建議使用 BigDecimal。另外仲有 BigInteger,都一樣係 arbitrary-precision
箭嘴解釋
實線Automatic/implicit type conversion 自動轉換/隱式轉換(如要反方向轉換,必須進行 explicit type casting 顯式轉換)
虛線轉換後有可能會失去精確度

3.3.2.1 Automatic type conversion 示範

以下為示範:
1byte b = 1; 2 3short s = b; // implicit type conversion 4byte b2 = s; // compilation error, Type mismatch: cannot convert from short to byte 5byte b3 = (byte) s; // explicit type casting 6 7int i = s; // implicit type conversion 8short s2 = i; // compilation error, Type mismatch: cannot convert from int to short 9short s3 = (short) i; // explicit type casting 10 11char c = 1; 12int i2 = c; // implicit type conversion 13char c2 = i2; // compilation error, Type mismatch: cannot convert from int to char 14char c3 = (char) i2; // explicit type casting 15 16long l = i2; // implicit type conversion 17int i3 = l; // compilation error, Type mismatch: cannot convert from long to int 18int i4 = (int) l; // explicit type casting 19 20float f = i2; // implicit type conversion 21int i5 = f; // compilation error, Type mismatch: cannot convert from float to int 22int i6 = (int) f; // explicit type casting 23 24double d = l; // implicit type conversion 25long l2 = d; // compilation error, Type mismatch: cannot convert from double to long 26long l3 = (long) d; // explicit type casting

3.3.3 Primitive data types 既 wrapper classes

Primitive data types 唔容許 null,所以一定有一個明確既 value。但如果我地唔想咁,我地可以用 wrapper classes。
Primitive types 對應既 wrapper classes(大部分都係將第一隻字轉大草):
  • Boolean (true / false)
  • Integer
  • Long
  • Float
  • Double
  • Byte
  • Character
以上 wrapper classes 通常用喺 DTO(data transfer objects),因為容許 null
文字既 data type 係 String,呢個就冇 primitive type,一定係 object。

3.3.4 Autoboxing 及 unboxing

為左方便使用 primitive types 同 primitives 既 wrapper classes,Java 原生支持 autoboxing 同 unboxing(autoboxing 既反方向)。
Autoboxing,即係由 primitive 自動 box/wrap 成 wrapper class,會喺以下情況下發生:
Integer num = 1;
1public static void main(String[] args) { 2 3 // autobox int 1 成 Integer 1 4 5 foo(1); 6} 7 8private static void foo(Integer num) { 9 // do sth 10}
Unboxing,即係由 wrapper class 自動 unbox/unwrap 成 primitive,會喺以下情況下發生:
int num = new Integer(1);
1public static void main(String[] args) { 2 3 // unbox Integer 1 成 int 1 4 5 foo(new Integer(1)); 6} 7 8private static void foo(int num) { 9 // do sth 10}
Autoboxing 同 unboxing 同時發生:
1// 先 unbox Integer 3 成 int 3 2// 再計 int 3 + int 2 3// 再將 int 5 autobox 成 Integer 5 4Integer num = new Integer(3) + 2; 5 6// 先 unbox Integer num 成 int 5 同 unbox Integer 4 成 int 4 7// 再計 int 5 + int 4 8// 再將 int 9 autobox 成 Integer 9 9num += new Integer(4);
注意如果 unbox 既時候 object value 係 null,咁喺 runtime 就會出現 NullPointerException

3.3.5 Array / Collection / Map

當我地想將好幾個同一個 type 既 data 放埋一齊成為一個組合,我地可以用 array、Collection 或者 Map。不過 array 基本上好少機會會用到,因為功能唔及得上 Collection 咁多,例如 addremove 之類能夠改變長度既操作;或者 TreeSet 咁既會自己排序既 implementation;又可以喺 getter 度 return Collections.unmodifiableList(list),防止修改 DTO object 既 property value,達到 immutability。喺 web application 裡面更加可以話係冇人會用 array。
Array 既長度係固定既:
String[] arr = new String[4];
int[] arr = new int[] { 3, 6 }; arr[0] = 7; arr[2] = 3; // 因為只有 0 同 1 兩個 index,呢行會爆 ArrayIndexOutOfBoundsException
CollectionListSet)及 Map 既長度係 dynamic 既,任得你加(上限非常大)。
CollectionList subinterface:
List<String> list = new ArrayList<>();
List<String> list = new LinkedList<>();
List<String> list = new Vector<>();
list.add("Michael"); list.add("Ben"); // 可以繼續 add 落去
註:List 係會保留插入順序。
CollectionSet subinterface(唔容許重複):
Set<String> set = new HashSet<>(); // 不保留插入順序
Set<String> set = new LinkedHashSet<>(); // 保留插入順序
Set<String> set = new TreeSet<>(); // 自然順序
set.add("Michael"); set.add("Michael"); // 因為已經存在,add 完唔會有分別 // 可以繼續 add 落去
至於 Map,就可以放 key-value pairs(唔容許重複既 key,否則新既 entry 會 overwrite 舊既 entry):
Map<String, Object> map = new HashMap<>(); // 不保留插入順序
Map<String, Object> map = new LinkedHashMap<>(); // 保留插入順序
Map<String, Object> map = new TreeMap<>(); // 自然順序
map.put("Michael", 25); map.put("Michael", 30); // overwrite 左 Michael=25 // 可以繼續 put 落去
以上既 listsetmap 都用左 polymorphism,即係 assign subclass 或 implementation class 去一個用 superclass 或 interface 既 type 去 declare 既 variable(List<String> list)度。
  • List 係 interface,而 ArrayListLinkedListVector 都係 implementsList
  • Set 係 interface,而 HashSetLinkedHashSet 都係 implementsSet
  • Map 係 interface,而 HashMapLinkedHashMap 都係 implementsMap

3.3.6 自定義 types

當我地自定義 types,要知道有以下幾種叫法(或者形容關係):
Java type 既款式解釋
Concrete class只要所有 methods 都有 method body(implementation)就可被視為 concrete class,可以直接 new,如 new Foo()
Implementation class一個 implements 左某個 interface 既 class
Abstract class抽象層,當一個 class 有至少一個 method 缺少 method body(即係 abstract 左,原因可以係因為寫明左係 abstract,或者 implements 左個 interface 而繼承左佢既 abstract methods),呢個 class 就必須加上 abstract。Abstract class 可以成為 superclass 畀 subclass 去 extends。唔可以直接 new,除非你「就地」建立 anonymous class
Subclass一個 extends 左某個 superclass(可以係 concrete class,亦可以係 abstract class)
Superclass當一個 class(無論係 concrete class 抑或係 abstract class)被 extends,就可以被視為係 superclass
Anonymous class匿名 class,其實冇必要用,因為寫 concret class 會更好,亦有助於 unit testing。有兩個情況會用到 anonymous class,一係想用一個 abstract class 或 interface 但又唔想寫 concrete implementation class,一係想就地 override 一個 concrete class 既某啲 methods。寫 anonymous class 既時候要加 {},即 new Foo() { /* 為 abstract methods 提供 method body */ }
Interface所有非 default 既 methods 都冇 method body(冇 implementation,亦係 abstract),亦冇 property。等於一份 contract,迫啲 implements 左呢個 interface 既 concrete class 一定要實現曬呢個 interface 有既 methods。唔可以直接 new,除非你「就地」建立 anonymous class
Superinterface就好似 superclass 咁,當一個 interface 被一個 interface extends 時,就可以被視為係 superinterface
Subinterface就好似 subclass 咁,係一個 extends 左一個或多個 interfaces 既 interface
Enum一舊野,主要用黎對比(if-else 或者 switch)。用於 ORM 時可以對應 MySQL 既 ENUM type
Annotation用黎標籤 type、method、property 或 parameter(不包括 local variable),要透過 reflection 先可以用到

3.3.6.1 Concrete class 既例子

1public class Foo { 2 3 // 只要所有 methods 都有 method body,就係 concrete class 4 5 public void play() { 6 // do sth 7 } 8}

3.3.6.2 Abstract class 既例子

例子一:
1public abstract class AbstractFoo { 2 3 // 因為有至少一個 abstract method,所以呢個 class 要係 abstract 4 5 protected abstract void play(); 6}
例子二:
1public abstract class AbstractFoo extends Bar { 2 3 // 繼承左 abstract 既 play() 4} 5 6abstract class Bar { 7 8 // 下面有一個 abstract method 9 10 protected abstract void play(); 11}
例子三:
1public abstract class AbstractFoo implements Bar { 2 3 // 繼承左 abstract 既 play() 4} 5 6interface Bar { 7 8 // interface 既所有 methods 都係 abstract 9 10 void play(); 11}

3.3.6.3 Subclass 及 superclass 既例子

1public class Foo extends Bar { 2 3 // extends 左 Bar,所以係一個 subclass(methods 有齊 method body,所以亦係 concrete class) 4 5 @Override 6 protected void play() { 7 // do sth 8 } 9} 10 11abstract class Bar { 12 13 // 被 Foo extends,所以算係 Foo 既 superclass 14 15 protected abstract void play(); 16}

3.3.6.4 Implementation class 及 interface 既例子

1public class Foo implements Bar { 2 3 // implements 左 Bar,所以係一個 implementation class(methods 有齊 method body,所以亦係 concrete class) 4 5 @Override 6 public void doSth() { 7 // do sth 8 } 9} 10 11interface Bar { 12 13 // interface 裡面既 methods 一定係 public 同 abstract 14 15 void doSth(); 16}

3.3.6.5 Anonymous class 既例子

1public class Example { 2 public static void main(String[] args) { 3 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 // do sth 8 } 9 }).start(); 10 } 11}
解釋:
上面段 code 既 new Runnable() {} 就係 anonymous class。
由於 Runnable 係一個 interface,我地唔可以直接 new 佢,除非以 anonymous class 既做法,即係加 {},同埋為所有 abstract methods 提供 method body。 當然我地可以寫一個 class 去 implements Runnable,然後 new 呢個自定義 class。

3.3.7 以 lambda 取代 anonymous class

以下呢個例子既 anonymous class 可以被新式 lambda 寫法取代:
1public class Example { 2 public static void main(String[] args) { 3 4 // new Runnable() {} 係 anonymous class 5 6 new Thread(new Runnable() { 7 @Override 8 public void run() { 9 // do sth 10 } 11 }).start(); 12 } 13}
以 Java 8 既新 lambda 功能黎簡化:
1public class Example { 2 3 public static void main(String[] args) { 4 5 new Thread(() -> { /* do sth */ }).start(); 6 } 7}
解釋:
() -> {} 係 lambda 語法。上面兩段 code call 緊既都係 Thread(Runnable) 既 constructor,只係自從 JDK 8 開始, 我地有一個方便簡潔啲既方法去寫,避免 anonymous class 要寫咁多行 code。
因為 JDK 既 Runnable 只有一個叫 run 既 method,所以我地先可以用 lambda。 亦因為咁,所以 Runnable 可以 annotate @FunctionalInterface
註:C# 同 JavaScript 都有 lambda syntax。

3.3.8 Naming convention 命名原則/慣例

Java 既命名慣例係:
  • UpperCamelCase:type 名
  • lowerCamelCase:property、local variable、method 名、parameter
  • UPPER_UNDERSCORE_CASE:constant 名(不變值)

3.4 如何設計 class

一般我地會有以下幾種 class 設計:
設計描述例子
Service class擁有 business logic 既 class自定義,冇例子
Data Access Object (DAO) class用黎 access DB,每個 method 可以被視為一句 SQL任何 implements JpaRepository 既 class
Plain old Java object(POJO)、Value Object(VO)、Data transfer object(DTO)class用黎儲住 data,喺不同既 class 之間使用自定義,以 properties、getters、setters 為主既 class,可以有啲自定義 methods
Utility class工具類,與 helper class 相似,stateless(唔會有 non-static properties),而且全部都係 static methods(有啲情況下會令到某啲 test 較難寫)Apache Commons Lang3 既 StringUtils
Helper class工具類,與 utility class 相似,可以係 stateful(可以有 non-static properties),未必有 static methods,呢個 class 可以係需要 construct(e.g. new MyHelper())或者用 singleton pattern(runtime 只有一個 object copy)(e.g. MyHelper.getInstance()JDK 既 Calendar
註:如果我地 apply 唔同既 design patterns,亦可以有更多不同種類既 class。

3.5 如何寫 method

一個 method 有以下部分:
部分描述
ModifiersAccess modifier、staticabstractfinalsynchronized
Return type冇野 return 就 void,有就畀個 type 佢
Method 名應以 lowerCamelCase 命名
Parameters冇就留空,有就加上去,最後一個 parameter 可以係 ... varargs(等同 array)
Method bodyImplementation,如果 method 係 abstract,就唔需要 {},直接 ; 就得
冇 return type 既例子:
1public void foo(String message) { 2 3 // do sth 4 5 if (new Random().nextInt()==0) { 6 System.out.println("Lucky!"); 7 return; // 用黎控制 flow,提早返回 8 } 9 10 System.out.println("No luck!"); 11 12 return; // 如果寫喺最後一行,就可以省略,否則用黎控制 flow 13}
有 return type 既例子:
public String fullCapitalLetters(String message) { return message==null ? null : message.toUpperCase(); }

3.5.1 Overload 一個 method

Method overloading 即係同一個 method 名,但 method parameters 唔同。
以下例子中,sayHi method 有三個,當中運用左 method overloading。
喺 Java 裡面 call methods,一定要中曬 delcare 左既 parameters 既數量、argument type 適合(subclass 或 implementation 都可以)先得。
1public class Foo { 2 3 public static void main(String[] args) { 4 sayHi(); // Hi 5 sayHi("Michael"); // Hi, Michael 6 sayHi("Michael", true); // Hi, MCIHAEL 7 } 8 9 private static void sayHi() { 10 sayHi(null, false); 11 } 12 13 private static void sayHi(String message) { 14 sayHi(message, false); 15 } 16 17 private static void sayHi(String message, boolean isUpperCase) { 18 if (message==null) { 19 System.out.println("Hi"); 20 } else { 21 System.out.println("Hi, " + (isUpperCase ? message.toUpperCase() : message)); 22 } 23 } 24}
JavaScript 就冇需要咁寫,因為 JavaScript 可以用同一個 function 名,但落曬有可能畀既 parameters 去個 function 度, 然後 call function 既時候畀少啲 arguments 都係可以既,甚至畀多過個 function 接受既都得。除此之外,JavaScript 既 non-arrow function 仲可以用一個叫 arguments 既 array 黎拎到 caller pass 入去既 arguments,換言之 JavaScript 既 function 係可以唔 declare parameters 但都拎到 arguments,自由度完勝 Java。
1// 所有可能出現或需要用到既 parameters 2function sayHi(message, isUpperCase) { 3 if (message) { 4 console.log("Hi, " + (isUpperCase ? message.toUpperCase() : message)); 5 } else { 6 console.log("Hi, who are you?"); 7 } 8} 9 10// 喺 arguments 裡面攞需要用到既 arguments 11function sayHello() { 12 const message = arguments && arguments.length >= 1 ? arguments[0] : undefined; 13 const isUpperCase = arguments && arguments.length >= 2 ? arguments[1] : undefined; 14 15 sayHi(message, isUpperCase); 16} 17 18// ----- 任意 arguments ----- 19 20sayHi(); // Hi, who are you? 21sayHi("Michael"); // Hi, Michael 22sayHi("Michael", true); // Hi, MICHAEL 23 24// ----- 畀多過個 method 接受既都得 ----- 25 26sayHi("Michael", true, "extra"); // Hi, MICHAEL 27 28// ----- 個 function 用左 arguments 而唔係 declare parameters ----- 29 30sayHello(); // Hi, who are you? 31sayHello("Michael"); // Hi, Michael 32sayHello("Michael", true); // Hi, MICHAEL

3.5.2 Override 一個 method

喺一個 subclass 或者 implementation class 裡面,我地可以 override methods,即係將繼承左既 method 重新定義 implementation。
1abstract class AbstractFoo { 2 3 protected abstract void sayHi(); 4} 5 6interface Playable { 7 8 void play(); 9 10 default void playTogether() { 11 // do sth 12 } 13} 14 15public class Foo extends AbstractFoo implements Playable { 16 17 @Override 18 protected void sayHi() { 19 // do sth 20 } 21 22 @Override 23 public void play() { 24 // do sth 25 } 26 27 @Override 28 public void playTogether() { 29 // do sth 30 } 31}
Eclipse 中間個版面既左手邊既 line number 旁邊會顯示邊啲 methods 有被 overridden,如下圖既白色、綠色箭嘴:

3.6 睇 libraries 既 Javadoc 以及實際 source code

3.6.1 喺 Eclipse 裡面睇

無論你想睇既係 JDK 內建既 class 或 method 既定義抑或係 3rd party library 既定義,都可以喺 IDE 度做到。
  1. 將 cursor 放喺 class 或 method 上面,等一兩秒,佢會顯示一個帶有 Javadoc 既 popup,除非 API developer 冇寫,否則都會有文字描述。 呢個時候可以撳 F2,或將 cursor 放喺呢個 popup 上面,等一秒,mouse 撳一撳個 popup 既文字,呢個時候就可以有多啲操作。
  2. 你亦可以按住 Ctrl 鍵,然後 mouse 撳落個 class 或 method 上,就可以直接踩入 API developer 寫既 code 裡面。

3.6.1.1 安裝 Enhanced Class Decompiler plugin

  1. Drag 個 Install 掣去 Eclipse 度安裝。
  2. 安裝最基本既 Core component 就夠。
  3. 去 menu bar > Window > Preferences > 左邊 filter text 打 file asso > 揀 File Associations > 右邊 File types 揀 .class without source > 下面 set Class Decompiler Viewer 做 default。
參考資料:

3.6.2 上官網睇 Javadoc

Google search:class 名 + 8 即可,通常都會搵到,唔得就 + java 8
inputstream 8,就會搵到 InputStream (Java Platform SE 8 ) - Oracle Help Center

3.7 JDK 內建實用 classes

下面係一啲基本既 JDK 內建 classes。如果唔夠用,我地可以利用 Maven repository 上面既其他 libraries。
Classes描述
System用黎簡單咁 print 下 log(開發用)、攞 environment variable 或者 system properties。
File同本地檔案、資料夾有關既操作都要用到。
Date(舊)、Calendar(舊)、LocalDateLocalDateTimeInstant日期、時間相關。
BigDecimal當我地處理含有小數點金額既時候,要小心小數點因為數學運算而失去精確度。我地應該用 JDK 既 BigDecimal(major unit)或者 Joda-Money library 裡面含貨幣訊息既 Money(支持 major unit 及 minor unit)。
PatternMatcher用黎做 regular expression(RegEx)運算。
Thread令程式可以 multithreading,畀多個線程同時運作,同時執行唔同既 Runnable