Java Basics
Java 核心概念與基礎知識參考。
CDI
Contexts and Dependency Injection
Do-it-Yourself Dependency Injection
Collection
Java Collections Framework provides data structures like List, Set, Map, and Queue.
ConcurrentHashMap
- Allows multiple threads to access entries concurrently
- Default: divided into 16 segments
- Default capacity: 16, load factor: 0.75
CopyOnWriteArrayList
- Thread-safe variant of ArrayList
- Creates a new copy of underlying array for write operations
classpath
The classpath is used by the Java runtime to locate classes and resources.
Encapsulation
| Modifier | Class | Package | Subclass (Same/Other Package) | Global |
|---|---|---|---|---|
| private | ⭕ | |||
| default | ⭕ | ⭕ | ||
| protected | ⭕ | ⭕ | ⭕ | |
| public | ⭕ | ⭕ | ⭕ | ⭕ |
Enum
int enum pattern
- deficient!
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;- No way of type safety and no convenience.
The compiler won’t complain if you pass an apple to a method that expects orange.
int enums are compile-time constants. They are compiled into the clients that use them.
If the int associated with an enum constant is changed, its clients must be recompiled.
No easy way to translate int enum constants into printable strings (all you see is a number).
Solution - Enum Types
Key points:
- enum improves type safety
- names of an enum type’s fields are in uppercase letters
- enum can be easily used in switch
- enum can be traversed
- enum can have fields, constructors, and methods
- We cannot create an instance of enum because the constructor is private
- We can write abstract methods in the enum and provide implementations
- enum may implement many interfaces but cannot extend any class (internally extends Enum class)
Advantages:
- They’re classes that export one instance for each enum constant via a public static final field
- They are a generalization of singletons
- Enums provide compile-time type safety
- You can translate enums into printable strings by calling toString() method
- Provide implementations of Object methods
- Implement Comparable, Serializable
public enum Apple {
FUJI, PIPPIN, GRANNY_SMITH
}
public enum Orange {
NAVEL, TEMPLE, BLOOD
}- Bad Practice
public enum AbuseEnum {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numMusicians() {
return ordinal() + 1; // Don't do this
}
}- Good Practice
public enum Ensemble {
ONE(1),TWO(2),THREE(3),
FOUR(4),FIVE(5),SIX(6),
SEVEN(7), EIGHT(8),NINE(9),
TEN(10),ELEVEN(11),TWELVE(12);
private final int num;
Ensemble(int n) {
this.num = n;
}
public int getNum() {
return num;
}
}Exception
Checked Exception 受檢例外
一定要處理的 Exception,因為這些狀況不一定可以事先避免,加上多為外在環境有關,所以一定得預先處理。
Unchecked Exception 非受檢例外
不一定要處理 Exception,因為這些狀況都是工程師 Write Code 時可以先避免的,所以 Java 不強制我們處理以增加程式碼的複雜度。
Generics
- PECS
- Producer : 只讀取,不能存 (Covariance)
- Consumer : 能存,但往外讀取只能用 Object (Contravariance)
I/O
graph RL
subgraph TOP
R[\Reader\] --> |character streams| Z{Object}
W[\Writer\] --> |character streams| Z
IS[\InputStream\] --> |bytes stream| Z
OS[\OutputStream\] --> |bytes stream| Z
end
subgraph Reader
1[StringReader] -->R
2[CharArrayReader] -->R
3[PipedReader] -->R
4[BufferedReader]:::R -->R
classDef R fill:#f32;
100[FileReader] -->|Node Stream| 5[InputStreamReader]:::R -->|ProcessingStream| R
classDef e fill:#ffffff;
101[\FilterReader\]:::R -->R
end
subgraph Writer
6[PrintWriter] --> W
7[CharArrayWriter] --> W
8[StringWriter] --> W
9[PipedWriter] --> W
10[\FilterWriter\]:::R --> W
11[FileWriter] --> |Node Stream| 13[\OutputStreamWriter\]:::R -->|Processing Stream| W
12[BufferedWriter]:::R --> W
end
subgraph InputStream
14[FileInputStream] --> IS
15[AudioInputStream] --> IS
16[ByteArrayInputStream] --> IS
17[PipedInputStream] --> IS
BI[BufferedInputStream]:::R --> 18[FilterInputStream]:::R --> IS
DI[DataInputStream]:::R --> 18
PI[PushbackInputStream]:::R --> 18
19[ObjectInputStream]:::R --> IS
20[SequenceInputStream]:::R --> IS
end
subgraph OutputStream
21[FileOutputStream] --> OS
23[PipedOutputStream] --> OS
25[ByteArrayOutputStream] --> OS
BO[BufferedOutputStream]:::R --> 22[FilterOutputStream]:::R --> OS
DO[DataOutputStream]:::R --> 22
PS[PrintStream]:::R --> 22
24[ObjectOutputStream]:::R --> OS
end
資料流 (Data Flow) 處理
輸入找源頭
graph LR
0((源頭 Source))
==> 1([低階Input_FileInputStream])
==> 2([高階Input_BufferedInputStream])
==> 3([任你串高階Input_??????])
==> infitity((程式 Program))
輸出找目的地
flowchart LR
infitity((程式 Program))
==> 3([任你串高階Output_??????])
==> 2([高階Output_BufferedOutputStream])
==> 1([低階Output_FileOutputStream])
==> dest((目的地 Destination))
關閉 I/O
- try-with-resource
- 只關閉最終包裝的高階流
Stream APIs
- Intermediate Operations
- Stateful
- Stateless
- Terminal Operation
- Short-Circuit
- Non-Short-Circuit
Intermediate operations are always lazy.
Stream<String> lazyDemo = Stream.of("hello", "world");
lazyDemo.peek(System.out::println);# empty - no outputStream<String> lazyDemo2 = Stream.of("hello", "world");
lazyDemo2.peek(System.out::println).collect(Collectors.toList());hello
world
[hello, world]
flowchart TB
S[Stream]
IO[Intermediate Operations]
Sf[Stateful]
Sl[Stateless]
TO[Terminal Operation]
SC[Short-Circuit]
NSC[Non-Short-Circuit]
S ====> IO
S ====> TO
IO ====> Sf
IO ====> Sl
TO ====> SC
TO ====> NSC
Stateless
當操作的處理不受之前元素影響,則為無狀態
- unordered, filter, map, mapToInt, mapToLong, mapToDouble
- flatMap, flatMapToInt, flatMapToLong, flatMapToDouble, peek
Stateful
當操作需要拿到目前為止處理的所有元素資訊之後才能繼續下去,則此操作則為有狀態
- distinct, sorted, limit, skip
Short-Circuit
Operation which helps us to optimize the computation and improve performance by avoiding unnecessary processing of elements.
- anyMatch, allMatch, noneMatch, findFirst, findAny, limit
Non-Short-Circuit
Refers to the fact that all elements must be processed to obtain the final result.
- forEach, forEachOrdered, toArray, reduce, collect, max, min, count
Functional Interface
| Interface | Description | Method(s) |
|---|---|---|
Predicate<T> | Represents a predicate (boolean-valued function) of one argument. | boolean test(T t) |
Consumer<T> | Represents an operation that accepts a single input argument and returns no result. | void accept(T t) |
Function<T, R> | Represents a function that takes one argument and produces a result. | R apply(T t) |
Supplier<T> | Represents a supplier of results. | T get() |
UnaryOperator<T> | Represents an operation on a single operand that produces a result of the same type as its operand. | T apply(T t) |
BinaryOperator<T> | Represents an operation upon two operands of the same type, producing a result of the same type as the operands. | T apply(T t1, T t2) |
BiPredicate<T, U> | Represents a predicate (boolean-valued function) of two arguments. | boolean test(T t, U u) |
BiConsumer<T, U> | Represents an operation that accepts two input arguments and returns no result. | void accept(T t, U u) |
BiFunction<T, U, R> | Represents a function that takes two arguments and produces a result. | R apply(T t, U u) |
Comparator<T> | Represents a comparison function for comparing two objects of the same type. | int compare(T o1, T o2) |
如以上皆不符合需求,請使用自定義
@FunctionalInterfaceSupplier
- Use
Supplierif it takes nothing : 如果需要的行為是不接受任何引數,然後傳回值,請使用Supplier
Consumer
- Use
Consumerif it returns nothing : 如果需要的行為是接受一個引數,然後處理後不傳回值,請使用Consumer
Function
- Use
Functionif it does both : 如果需要的是接受一個引數,然後以該引數進行計算後傳回結果,請使用Function
Predicate
- Use
Predicateif it returns a boolean : 如果接受一個引數,然後只傳回 boolean 值,請使用Predicate
SPI
Service Provider Interface
是 Java 提供的一套用來被第三方實現或擴展的接口,它可以用來啟用框架擴展和替換組件。
flowchart
subgraph Provide
Cer[Caller]
I[interface]
end
Impler[Service Provider]
Cer ---->|Call| I
Impler ---->|implementation| I
- Compared with API
flowchart
Cer[Caller]
subgraph Provide
I[interface]
Impler[Service Provider]
end
Cer ---->|Call| I
Impler ---->|implementation| I
Time
LocalDateTime
- ISO-8601 不帶時區的日期時間
- Immutable
適合日期的描述:例如用於生日、deadline等等。但是請記住,如果沒有偏移量/時區等附加訊息,一個時間是不能表示時間線上的某一時刻的。
2023-08-01T12:30:15Z[UTC]
- T : full date-time
- Z : UTC +0,格林威治時間
CLI
Document
javadoc -d doc MyClass.javaEnable Preview
- compile
javac --release 21 --enable-preview Demo.java- run
java --enable-preview Demojar
- build
*.classinto jar
jar cf <jar-file> <input-file(s)>jar cf JarExample.jar com/baeldung/jar/*.classjar cfm hi.jar MANIFEST.MF **/*.classVerify the JAR File
- verify that jar includes the correct files
jar tf myproject.jarjps & jstack
- Steps: check deadlock
- Find PID
jps- Capture Thread Dump
jstack <PID> > thread_dump.txtjavap
javap -verbose YourClass.classjava
java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'java -XX:+PrintCommandLineFlags -versionKeytool
Generate a key pair
keytool -genkeypair -alias local_ssl -keyalg RSA -keysize 2048 \
-storetype PKCS12 -keystore local-ssl.p12 -validity 365 \
-ext san=dns:localhostExport Certificate
keytool -export -keytool local-ssl.p12 -alias local_ssl -file local-cert.crtTopics
Why is Java slow?
- Dynamic Linking: Linking is done at run-time, every time the program runs
- Run-time Interpreter: Conversion of bytecode to native machine code happens at run-time
Objects.requireNonNull
- Fail-fast null checking
- Throws NullPointerException if argument is null
- Used for parameter validation