Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Core Concepts: A Comprehensive Review

Tech May 10 4

Primitive Data Types

Java provides eight primitive data types organized into three categories:

  • Numeric types: byte, short, int, long, float, double
  • Character type: char
  • Boolean type: boolean

Integer types have the following bit sizes: byte (8 bits), short (16 bits), int (32 bits), and long (64 bits). Floating-point types include float (32 bits) and double (64 bits).

Type conversion hierarchy from lowest to highest:

byte, char, short (same level) → int → float → long → double

Automatic type conversion occurs when moving from lower to higher in the hierarchy, handled automatically by the compiler. When performing calculations, if operand types are lower than int, the result automatically promotes to int. When mixing different types, the final result takes the highest-ranked type among operands.

Explicit casting (强制类型转换) is required when converting from higher to lower. This requires careful attention to value ranges and precision loss.

The char type stores single Unicode characters, while boolean represents logical values with only two possible values: true or false.

Wrapper Classes

Each primitive type has a corresponding wrapper class in java.lang:

Primitive Wrapper
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

Why use wrapper classes?

  1. Facilitate type conversion: Wrapper classes provide utility methods for converting between types. For example, converting String to int:
int value = Integer.parseInt("123");
Integer wrapped = Integer.valueOf("123");
  1. Enable object-based operations: Many APIs require object parameters. Wrapper classes allow primitives to be used where objects are expected. This is essential for generics like Map<String, Integer>.

Important: When comparing wrapper objects, always use equals() instead of ==.

Integer first = 127;
Integer second = 127;
Integer third = 128;
Integer fourth = 128;

System.out.println(first == second);      // true
System.out.println(first.equals(second)); // true
System.out.println(third == fourth);      // false
System.out.println(third.equals(fourth)); // true

This behavior occurs because Integer uses an internal cache for values between -128 and 127.

Modifiers

Access Modifiers

Modifier Same Class Same Package Subclass Other Packages
public
protected
default
private

Non-Access Modifiers

static: Modifies class variables and methods.

  • Class variables exist as a single copy regardless of how many instances exist. Also called class variables. Local variables cannot be static.
  • Static methods cannot access non-static members. They can be invoked directly via the class name and cannot use this or super.

final: Modifies classes, methods, and variables.

  • A final class cannot be extended.
  • A final method cannot be overridden.
  • A final variable becomes a constant and cannot be reassigned.

abstract: Creates abstract classes and methods.

  • An abstract class cannot be instantiated but can be used as a declared type. It serves as a partial implementation requiring subclasses to complete it.
  • An abstract method has only a signature with no implementation, requiring subclasses to provide the body.

synchronized: Ensures only one thread can execute the method at a time.

transient: Indicates the JVM should skip the field during serialization.

native: Indicates implementation is provided in another programming language.

Object-Oriented Principles

Encapsulation

Encapsulation acts as a protective barrier, preventing external code from directly accessing a class's internal data. Interaction occurs only through well-defined interfaces.

Benefits:

  • Reduces coupling between components
  • Allows internal implementation to change without affecting other parts
  • Provides finer control over member variables
  • Hides implementation details from users

Inheritance

Inheritance enables the creation of hierarchical class structures. A subclass inherits fields and methods from its parent class, promoting code reuse.

class Vehicle {
    protected int speed;
    public void move() { }
}

class Car extends Vehicle {
    private int doors;
}

Trade-off: While inheritance improves code reuse, it also increases coupling between classes.

Polymorphism

Polymorphism allows objects to take different forms during execution.

Advantages:

  • Substitutability: Existing code works with new subtypes
  • Extensibility: Adding new subclasses doesn't affect existing code
  • Interface flexibility: Superclasses define contracts that subclasses implement
  • Simplified code: Reduces conditional logic when handling different types
void drawShape(Shape s) {
    s.render(); // Works with any Shape subclass
}

Collections Framework

List Interface

List is an ordered collection that allows duplicate elements and positional access.

Implementation Characteristics
ArrayList Array-based, fast random access, slow insertion/deletion in middle
LinkedList Doubly-linked, fast insertion/deletion, slow random access. Also implements Deque
Vector Synchronized ArrayList, thread-safe but slower

Guideline: Use ArrayList for frequent reads, LinkedList for frequent insertions/deletions. For synchronized lists, prefer Collections.synchronizedList() over Vector.

Map Interface

Map stores key-value pairs. Keys must be unique, values can be duplicated.

Implementation Characteristics
HashMap Hash-based, allows one null key and multiple null values, not thread-safe
TreeMap Red-black tree, entries sorted by keys, no null keys, not thread-safe
LinkedHashMap Maintains insertion order via double-linked list, not thread-safe
Hashtable Legacy synchronized implementation, no null keys/values
ConcurrentHashMap Segment-based locking, optimized for concurrent access

Guideline: HashMap for general use, TreeMap for sorted keys, LinkedHashMap for insertion order, ConcurrentHashMap for multithreaded scenarios.

Set Interface

Set contains no duplicate elements.

  • HashSet: Hash-based, unordered, best performence
  • TreeSet: Sorted order, uses Comparable or Comparator
  • LinkedHashSet: Maintains insertion order

Multithreading

Multithreading enables concurrent execution of multiple code paths within a single program.

Thread Lifecycle

  1. New: Thread object created
  2. Runnable: start() called, waiting for CPU allocation
  3. Running: run() executing
  4. Blocked: Temporarily paused, waiting for resources
  5. Terminated: Thread completed execution

Thread Creation Approaches

// Approach 1: Implement Runnable
class Task implements Runnable {
    public void run() { }
}
new Thread(new Task()).start();

// Approach 2: Extend Thread
class Worker extends Thread {
    public void run() { }
}
new Worker().start();

// Approach 3: Callable with Future
class Computation implements Callable<Integer> {
    public Integer call() { return 42; }
}
Future<Integer> result = executor.submit(new Computation());

Note: Always use start() to launch threads, not run().

Guideline: Use inheritance for single-threaded scenarios, implement Runnable/Callable for multiple threads.

Key Methods

  • sleep(ms): Pauses current thread without releasing locks
  • join(): Waits for thread to complete
  • yield(): Temporarily yields CPU to other threads
  • wait(): Releases object lock, must be called within synchronized block
  • notify(): Wakes one waiting thread
  • setPriority(): Adjusts thread priority (1-10)

Synchronization Mechanisms

synchronized: JVM-managed lock. Blocks thread access, non-fair scheduling. Guarantees atomicity, visibility, and ordering.

Lock: Programmatic locking via java.util.concurrent.locks. More flexible, supports fairness configuration. Non-blocking tryLock available.

volatile: Ensures visibility of changes across threads. Prevents instruction reordering. Cannot guarantee atomicity for compound operations.

Thread Safety Guidelines

  • Local primitive variables are always thread-safe
  • Local object references are thread-safe if not escape to other threads
  • Shared mutable state requires synchronization

I/O Streams

Character Streams

Abstract classes: Reader, Writer

  • FileReader/FileWriter: File operations
  • BufferedReader/BufferedWriter: Buffered operations for efficiency

Byte Streams

Abstract classes: InputStream, OutputStream

  • FileInputStream/FileOutputStream: File operations
  • BufferedInputStream/BufferedOutputStream: Buffered operations

Guideline: Use character streams for text files, byte streams for binary files (images, videos).

I/O Models Comparison

Model Blocking Use Case
BIO Synchronous blocking Fixed connections, low concurrency
NIO Non-blocking, synchronous High concurrency, short connections (chat servers)
AIO Asynchronous non-blocking Long connections, high concurrency

NIO components: Selector (multiplexing), Buffer (data container), Channel (data channel). Netty and Mina are popular NIO frameworks.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.