Java Core Concepts: A Comprehensive Review
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?
- Facilitate type conversion: Wrapper classes provide utility methods for converting between types. For example, converting
Stringtoint:
int value = Integer.parseInt("123");
Integer wrapped = Integer.valueOf("123");
- 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
thisorsuper.
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
- New: Thread object created
- Runnable:
start()called, waiting for CPU allocation - Running:
run()executing - Blocked: Temporarily paused, waiting for resources
- 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 locksjoin(): Waits for thread to completeyield(): Temporarily yields CPU to other threadswait(): Releases object lock, must be called within synchronized blocknotify(): Wakes one waiting threadsetPriority(): 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 operationsBufferedReader/BufferedWriter: Buffered operations for efficiency
Byte Streams
Abstract classes: InputStream, OutputStream
FileInputStream/FileOutputStream: File operationsBufferedInputStream/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.