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

ModifierClassPackageSubclass (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

  1. try-with-resource
  2. 只關閉最終包裝的高階流

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 output
Stream<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

InterfaceDescriptionMethod(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)
如以上皆不符合需求,請使用自定義 @FunctionalInterface

Supplier

  • Use Supplier if it takes nothing : 如果需要的行為是不接受任何引數,然後傳回值,請使用 Supplier

Consumer

  • Use Consumer if it returns nothing : 如果需要的行為是接受一個引數,然後處理後不傳回值,請使用 Consumer

Function

  • Use Function if it does both : 如果需要的是接受一個引數,然後以該引數進行計算後傳回結果,請使用 Function

Predicate

  • Use Predicate if 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

Java Time API

LocalDateTime

  • ISO-8601 不帶時區的日期時間
  • Immutable
適合日期的描述:例如用於生日、deadline等等。但是請記住,如果沒有偏移量/時區等附加訊息,一個時間是不能表示時間線上的某一時刻的。

2023-08-01T12:30:15Z[UTC]

  1. T : full date-time
  2. Z : UTC +0,格林威治時間

CLI

Document

javadoc -d doc MyClass.java

Enable Preview

  • compile
javac --release 21 --enable-preview Demo.java
  • run
java --enable-preview Demo

jar

  • build *.class into jar
jar cf <jar-file> <input-file(s)>
jar cf JarExample.jar com/baeldung/jar/*.class
jar cfm hi.jar MANIFEST.MF **/*.class

Verify the JAR File

  • verify that jar includes the correct files
jar tf myproject.jar

jps & jstack

  • Steps: check deadlock
  • Find PID
jps
  • Capture Thread Dump
jstack <PID> > thread_dump.txt

javap

javap -verbose YourClass.class

java

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'
java -XX:+PrintCommandLineFlags -version

Keytool

Generate a key pair

keytool -genkeypair -alias local_ssl -keyalg RSA -keysize 2048 \
-storetype PKCS12 -keystore local-ssl.p12 -validity 365 \
-ext san=dns:localhost

Export Certificate

keytool -export -keytool local-ssl.p12 -alias local_ssl -file local-cert.crt

Topics

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