Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Java Core Programming: From Syntax Fundamentals to Reflection and Streams

Tools Sep 6 1

Operators and Control Flow

Java provides arithmetic, relational, bitwise, logical, assignment, and conditional (?:) operators. Program execution order is managed through sequential, branching (if, switch), and looping (for, while, do...while) structures.

Arrays

Creating and Initializing Arrays

Declaration, creation, and initialization are the three key steps for an array. Dynamic initialization specifies the length, while static initialization specifies element values directly.

Memory Allocation

  • Stack Memory: Stores local variables.
  • Heap Memory: Stores new-created instances and objects. Each has an address value; garbage collection reclaims it when no longer referenced.

Aliasing Arrays

Assigning one array variable to another makes them reference the same heap object. Modifying elements through one alias affects the other.

int[] scores = new int[5];
scores[0] = 10;
int[] aliasedScores = scores;
aliasedScores[0] = 20; // scores[0] is now also 20

Object-Oriented Fundamentals

Classes and Objects

A class is a blueprint; an object is a concrete instance. A constructor initializes new objects and must have the same name as the class, with no return type. Always invoke constructors with the new operator.

public class Employee {
    private String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
}

Object variables store references to objects, not the objects themselves.

Fields: Static vs. Instance

Static fields (class variables) are declared with static, belong to the class, and are shared across all instances. Access them using the class name.

public class Configuration {
    public static String appName;
    private static int instanceCount;
    
    public static int getInstanceCount() {
        return instanceCount;
    }
}

Instance fields (member variables) lack static and are unique to each object. They should generally be private, with access provided via getters/setters.

Methods

Methods define behavior.

Static methods can only directly access static members of the class. They cannot access instance fields or methods without an object reference.

public class MathUtils {
    public static double average(double x, double y) {
        return (x + y) / 2;
    }
}

Member methods operate on specific objects. Java passes object references by value, meaning a method can modify the referenced object's state but cannot make the original reference point to a new object. this distinguishes instance fields from local parameters.

Parameter Passing

  • Primitive types are passed by value; modifications inside a method do not affect the original variable.
  • Object references are also passed by value. The method receives a copy of the reference. Modifying the object's internal state is visible to the caller, but reassigning the copy does not affect the caller's reference.
public class ValueDemo {
    public static void modify(int primitive, StringBuilder sb) {
        primitive = 100; // No effect outside
        sb.append(" updated"); // Object state changed
        sb = new StringBuilder("New"); // Reference reassigned, no effect outside
    }
}

Method Overloading

Multiple methods in the same class can share a name, provided their parameter lists differ in type, count, or order. Return types alone cannot distinguish overloaded methods.

Inheritance and Polymorphism

Inheritance (extends)

Java supports single inheritance. A subclass inherits all non-private members of its superclass but can only directly access visible ones. To initialize inherited private fields, a subclass constructor must invoke a superclass constructor using super().

public class Manager extends Employee {
    private double bonus;

    public Manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }
}

Method Overriding

A subclass may provide a specific implementation for an inherited method, keeping the signature and return type compatible. final, static, and private methods cannot be overridden.

Keywords this and super

  • this resolves naming conflicts between instance fields and local variables; this(args) invokes another constructor in the same class.
  • super invokes overridden superclass methods or constructors, or accesses shadowed instance fields.

Polymorphism

A superclass reference can point to any of its subclass objects. The compile-time type determines which methods are accessible, while the runtime type determines which overriding implementation is executed. Fields do not exhibit polymorphic behavior; they are resolved at compile time.

class Shape {
    public String type = "Shape";
    public void draw() { System.out.println("Generic shape"); }
}
class Circle extends Shape {
    public String type = "Circle";
    @Override
    public void draw() { System.out.println("Drawing circle"); }
}
// Usage:
Shape shape = new Circle();
shape.draw(); // Output: Drawing circle
System.out.println(shape.type); // Output: Shape

Casting allows treating an object as its actual type. Downcasting ((SubClass) superclassRef) may throw a ClassCastException if the object's runtime type is incompatible. Always verify using instanceof.

if (shape instanceof Circle) {
    Circle c = (Circle) shape;
    c.specificCircleMethod();
}

Final Modifier

  • final class: Cannot be subclassed.
  • final method: Cannot be overridden.
  • final field: Value must be assigned once. For object references, the binding to the object is fixed, but the object's internal mutable state can still change.

Abstract Classes and Interfaces

An abstract class can contain both abstract and concrete methods, while interfaces (keyword interface) primarily define abstract behavior. A class implements an interface and must provide concrete implementations for all abstract methods.

Since Java 8, interfaces can also include default methods (with a body) and static methods. Default methods resolve conflicts via class-priority rules or explicit overriding.

interface Printable {
    void print();
    default void log() { System.out.println("Logging..."); }
    static String format(String s) { return "---" + s + "---" ; }
}

Enumerations (enum)

An enum defines a fixed set of named constant objects. Each constant can have its own fields, constructors, and method implementations.

enum Size {
    SMALL("S"), MEDIUM("M"), LARGE("L");
    private String abbreviation;
    private Size(String abbreviation) { this.abbreviation = abbreviation; }
    public String getAbbreviation() { return abbreviation; }
}

Exception Handling

Exceptions are objects thrown when errors occur. Throwable is the root class.

  • Checked exceptions must be caught or declared in the method signature (throws).
  • Unchecked exceptions (RuntimeException and its subclasses) do not require explicit handling.

Try-Catch-Finally

The try block encloses guarded code. Matching catch blocks handle thrown exceptions. The finally block always executes, regardless of exceptions or return statements, making it ideal for resource cleanup.

try {
    FileReader reader = new FileReader("data.txt");
    // operations
} catch (FileNotFoundException e) {
    System.err.println("File missing.");
} finally {
    // close resources
}

Manually Throwing Exceptions

Use the throw keyword to explicitly create and throw an exception object.

if (amount < 0) {
    throw new IllegalArgumentException("Amount cannot be negative");
}

Generics

Generics parameterize types, enforcing compile-time safety and eliminating casts. A generic type variable is a placeholder replaced with a concrete type upon usage.

Defining Generic Classes and Methods

public class Container<T> {
    private T content;
    public T getContent() { return content; }
    public void setContent(T content) { this.content = content; }
}

public <E> void printArray(E[] elements) { /* ... */ }

Type Erasure

At runtime, generic type information is erased. Type parameters are replaced with their bounds (Object if unbounded). The compiler inserts bridge methods and casts to maintain polymorphism and type safety.

Constraints

  • Cannot create instances of type parameters (new T()).
  • Cannot create arrays of parameterized types (new ArrayList<String>[10]).
  • Runtime type checks apply only to raw types.

Multithreading

Creating Threads

Two primary approaches exist:

  1. Extend the Thread class and override its run() method.
  2. Implement the Runnable interface and pass an instance to a Thread constructor.

The second approach is preferred due to Java's single-inheritance model. Start a thread with the start() method, not by calling run() directly.

class Task implements Runnable {
    @Override
    public void run() {
        System.out.println("Task running in " + Thread.currentThread().getName());
    }
}
new Thread(new Task()).start();

Thread Synchronization

Multiple threads accessing shared, mutable data cause race conditions.

  • Synchronized blocks and methods use an intrinsic lock (the this object for instance methods, the class object for static methods). Onnly one thread can hold a specific lock at a time.
  • The Lock API (e.g., ReentrantLock) offers explicit, more flexible lock management.
private int counter;
public synchronized void increment() {
    counter++;
}

// Or using ReentrantLock
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
    lock.lock();
    try { counter++; } finally { lock.unlock(); }
}

Thread Communication

wait(), notify(), and notifyAll() (defined in Object) enable threads to communicate about lock availability. These must be called from within a synchronized context on the same lock object. wait() temporarily releases the lock and suspends the thread until notified.

Key Difference: sleep() vs wait()

The core distinction is that sleep() retains the lock while pausing, whereas wait() releases it.

Core APIs

String, StringBuffer, StringBuilder

  • String is immutable, meaning operations like concatenation + with variables create new objects.
  • StringBuilder (non-synchronized) and StringBuffer (synchronized) are mutable sequences, ideal for repeated modification.

Comparators

  • The Comparable interface (method compareTo) defines the natural sorting order within a class.
  • The Comparator interface (method compare) allows on-the-fly definition of custom sorting logic.

Collections Framework

Key Interfaces

  • Collection: Root for List and Set.
  • List (e.g., ArrayList, LinkedList): Ordered, allows duplicates. ArrayList excels at random access; LinkedList excels at ensertions/deletions.
  • Set (e.g., HashSet, TreeSet): Disallows duplicates. HashSet relies on hashCode() and equals() for uniqueness; TreeSet relies on Comparable or Comparator and maintains sorted order.
  • Map (e.g., HashMap, TreeMap): Stores key-value pairs. HashMap permits one null key; TreeMap sorts by keys.

Iteration Patterns

  • Use an explicit Iterator or an enhanced for-loop.
  • The for-each loop translates to an iterator under the hood. During iteration, you may modify an object's state, but you cannot replace the current element in the collection.
for (String item : list) {
    System.out.println(item);
}

I/O Streams

  • Byte Streams (InputStream/OutputStream) handle raw binary data.
  • Character Streams (Reader/Writer) handle text data.
  • Buffered streams (BufferedInputStream, BufferedOutputStream) improve performance by reducing system calls.

The File class represents file and directory pathnames in an abstract, system-independent manner. It does not read or write data but provides metadtaa.

Reflection

Reflection allows a program to inspect and manipulate classes, fields, methods, and constructors at runtime.

  1. Obtain a Class instance via Class.forName(), ClassName.class, or object.getClass().
  2. Use getConstructor() to create instances.
  3. Use getField() or getDeclaredField() to access and modify field values.
  4. Use getMethod() and invoke() to call methods.

To access private members, call setAccessible(true) on the target reflectively obtained object.

Class<?> clazz = Class.forName("com.example.User");
Constructor<?> ctor = clazz.getConstructor(String.class);
Object obj = ctor.newInstance("Jane");

Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
System.out.println(nameField.get(obj));

Method setName = clazz.getMethod("setName", String.class);
setName.invoke(obj, "Janet");

Lambda Expressions and Stream API

Lambda and Functional Interfaces

A functional interface contains exactly one abstract method. A lambda expression provides a concise implementation of this interface.

Runnable task = () -> System.out.println("Run via lambda");

Four core functional interfaces in java.util.function are:

  • Consumer<T>: void accept(T t)
  • Supplier<T>: T get()
  • Function<T,R>: R apply(T t)
  • Predicate<T>: boolean test(T t)

Method references (ClassName::methodName) are syntactic sugar for lambdas where a single existing method's signature matches the target interface.

Stream API

Streams perform functional-style operations on collections. They are not data structures but convey elements from a source through a pipeline of computational steps.

Creation: collection.stream(), Arrays.stream(array), Stream.of(elements).

Intermediate Operations (lazy):

  • filter(Predicate)
  • map(Function)
  • sorted(Comparator)
  • distinct(), limit(n), skip(n)

Terminal Operations (trigger processing):

  • forEach(Consumer)
  • collect(Collectors.toList())
  • reduce(identity, accumulator)
  • count(), min(), max(), findFirst()

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

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