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 | 低 | 多線程編程會用到 |
transient | 低 | JDK 自帶既 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
咁多,例如 add
、remove
之類能夠改變長度既操作;或者 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
Collection
(List
、Set
)及 Map
既長度係 dynamic 既,任得你加(上限非常大)。
Collection
既 List
subinterface:
List<String> list = new ArrayList<>();
List<String> list = new LinkedList<>();
List<String> list = new Vector<>();
list.add("Michael");
list.add("Ben");
// 可以繼續 add 落去
註:List
係會保留插入順序。
Collection
既 Set
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 落去
以上既 list
、set
同 map
都用左 polymorphism,即係 assign subclass 或 implementation class 去一個用 superclass 或 interface 既 type 去 declare 既 variable(List<String> list
)度。
List
係 interface,而 ArrayList
、LinkedList
、Vector
都係 implements
左 List
Set
係 interface,而 HashSet
、LinkedHashSet
都係 implements
左 Set
Map
係 interface,而 HashMap
、LinkedHashMap
都係 implements
左 Map
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 有以下部分:
部分 | 描述 |
---|
Modifiers | Access modifier、static 、abstract 、final 及 synchronized |
Return type | 冇野 return 就 void ,有就畀個 type 佢 |
Method 名 | 應以 lowerCamelCase 命名 |
Parameters | 冇就留空,有就加上去,最後一個 parameter 可以係 ... varargs(等同 array) |
Method body | Implementation,如果 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 度做到。
- 將 cursor 放喺 class 或 method 上面,等一兩秒,佢會顯示一個帶有 Javadoc 既 popup,除非 API developer 冇寫,否則都會有文字描述。
呢個時候可以撳 F2,或將 cursor 放喺呢個 popup 上面,等一秒,mouse 撳一撳個 popup 既文字,呢個時候就可以有多啲操作。
- 你亦可以按住 Ctrl 鍵,然後 mouse 撳落個 class 或 method 上,就可以直接踩入 API developer 寫既 code 裡面。
3.6.1.1 安裝 Enhanced Class Decompiler plugin
- Drag 個 Install 掣去 Eclipse 度安裝。
- 安裝最基本既 Core component 就夠。
- 去 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 (舊)、LocalDate 、LocalDateTime 、Instant | 日期、時間相關。 |
BigDecimal | 當我地處理含有小數點金額既時候,要小心小數點因為數學運算而失去精確度。我地應該用 JDK 既 BigDecimal (major unit)或者 Joda-Money library 裡面含貨幣訊息既 Money (支持 major unit 及 minor unit)。 |
Pattern 及 Matcher | 用黎做 regular expression(RegEx)運算。 |
Thread | 令程式可以 multithreading,畀多個線程同時運作,同時執行唔同既 Runnable 。 |