Beginners Guide: Overview, Features, and Learning Path
A guide to understanding the big picture of Java — what it is, its key features, how code executes, and a recommended learning path through this dictionary.
What Is Java
Java is a programming language released in 1995 by Sun Microsystems (now Oracle). In short, it is a language designed so that code written once can run on any operating system.
This idea is captured in the slogan "Write Once, Run Anywhere." A program compiled on Windows can run on Linux or macOS without modification. The JVM (Java Virtual Machine), described below, is what makes this possible.
Where Java Is Used
Java is widely used in the following areas today.
- Web application backends (Spring Boot and similar frameworks)
- Android app development (an official language for Android alongside Kotlin)
- Large-scale enterprise and financial systems
- Microservices and cloud-native systems
Java became the dominant language for enterprise systems from the late 1990s through the 2000s, and that software continues to run in organizations around the world today.
Java's Characteristics — Strengths and Tradeoffs
Java has distinct characteristics compared to other languages, each of which can be a strength or a tradeoff depending on the situation. This is not a question of which is better — the fit depends on project scale, goals, and team structure.
Statically Typed Language
Java requires types to be declared explicitly for variables, method parameters, and return values. Type mismatches are detected at compile time (before execution).
// Declare variables with explicit types String name = "Gojo Satoru"; int power = 9999; // Assigning the wrong type causes a compile error // name = 100; // Error: incompatible types
Explicit types mean more code to write, but IDE (Integrated Development Environment — a tool combining code editing, execution, and debugging) autocompletion becomes more powerful and type mismatch bugs can be caught before the program runs — especially valuable in large codebases.
Garbage Collection
In C and C++, the programmer must manually allocate and free memory. In Java, the garbage collector (GC) automatically reclaims memory that is no longer in use.
This removes the burden of manual memory management, but the GC may cause brief pauses when it runs (known as "GC pauses"). In systems where real-time responsiveness is critical, these pauses can be a concern.
Object-Oriented Language
Java is designed around classes and objects. All logic is written inside classes, grouping data and behavior together.
// Class definition
class Fighter {
String name;
int power;
void attack() {
System.out.println(name + " attacks!");
}
}
// Create an instance
Fighter gojo = new Fighter();
gojo.name = "Gojo Satoru";
gojo.power = 9999;
gojo.attack(); // Gojo Satoru attacks!
Cross-Platform
Compiling Java code does not produce machine code for a specific OS or CPU (Central Processing Unit — the processor that executes computations). Instead, it produces bytecode (.class files). Bytecode runs on the JVM, so the same program can run on any OS where a JVM is available.
Strengths and Tradeoffs (Neutral Comparison)
| Aspect | Notes |
|---|---|
| Type safety | Static typing catches bugs before execution. More code to write for type declarations. |
| Memory management | GC handles it automatically. GC pauses can be an issue in latency-sensitive systems. |
| Performance | JIT compilation makes execution fast. JVM startup overhead exists. |
| Ecosystem | Large selection of libraries and frameworks. Dependencies can grow large. |
| Verbosity | Type declarations and class definitions add boilerplate. IDE completion helps. |
| Portability | Runs anywhere a JVM is available. JVM setup is required. |
| Learning curve | Requires understanding OOP and the type system. Abundant learning resources available. |
How Execution Works — .java → javac → .class → JVM
Running Java code involves two stages.
Seeing It in Action
Create a file called Hello.java.
Hello.java
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Gojo Satoru!");
}
}
Compile and run.
javac Hello.java java Hello Hello, Gojo Satoru!
The javac command compiles the source into Hello.class (bytecode). The java command runs that bytecode on the JVM.
JIT (Just-In-Time) Compilation
The JVM interprets bytecode line by line, but frequently executed code paths are compiled into native machine code and cached at runtime. This is called JIT compilation. Programs tend to run slowly right after startup and speed up as the JIT warms up.
Variables and Types
Java is a statically typed language, so the type of each variable must be declared explicitly.
// Primitive types int power = 9999; // integer (-2^31 to 2^31-1) long bigNumber = 10000000000L; // large integer (L suffix required) double height = 175.5; // floating-point (double precision) float ratio = 0.8f; // floating-point (single precision, f suffix required) boolean isSorcerer = true; // boolean char initial = 'G'; // single character (single quotes) // Reference type String name = "Gojo Satoru"; // text string (double quotes)
Note that String starts with a capital letter. Types like int and boolean are primitive types (they store the value directly), while String is a reference type (it stores a reference to an object).
var (Java 10 and Later)
From Java 10 onward, var enables type inference. The compiler infers the type from the right-hand side of the assignment.
// Using var (type inference) var name = "Itadori Yuji"; // inferred as String var power = 9999; // inferred as int // Equivalent to explicit declarations String name2 = "Itadori Yuji"; int power2 = 9999;
var can only be used for local variables. It cannot be used for fields or method parameters.
For more on variables and types, see Creating and Running .java Files.
Classes and Objects
Java is an object-oriented language. Data (fields) and behavior (methods) are grouped into classes. An instance (object) is created from a class and used at runtime.
class Sorcerer {
// Fields (data)
String name;
int cursedEnergy;
// Constructor (called when an instance is created)
Sorcerer(String name, int cursedEnergy) {
this.name = name;
this.cursedEnergy = cursedEnergy;
}
// Method (behavior)
void introduce() {
System.out.println("Sorcerer: " + name + " (Cursed Energy: " + cursedEnergy + ")");
}
}
// Create instances
Sorcerer gojo = new Sorcerer("Gojo Satoru", 9999);
Sorcerer itadori = new Sorcerer("Itadori Yuji", 500);
gojo.introduce(); // Sorcerer: Gojo Satoru (Cursed Energy: 9999)
itadori.introduce(); // Sorcerer: Itadori Yuji (Cursed Energy: 500)
Inheritance (extends)
A new class can inherit the fields and methods of an existing class.
// Parent class
class Sorcerer {
String name;
void curse() {
System.out.println(name + " used a cursed technique!");
}
}
// Child class (inherits from Sorcerer)
class SpecialGrade extends Sorcerer {
// Override the parent's method
@Override
void curse() {
System.out.println(name + " used Limitless!");
}
}
SpecialGrade gojo = new SpecialGrade();
gojo.name = "Gojo Satoru";
gojo.curse(); // Gojo Satoru used Limitless!
For more on classes, see new / Class Definition / Constructor. For inheritance, see extends / Override.
Collections — ArrayList / HashMap
Arrays have a fixed length. ArrayList allows elements to be added and removed dynamically.
ArrayList
import java.util.ArrayList;
ArrayList<String> members = new ArrayList<>();
members.add("Gojo Satoru");
members.add("Itadori Yuji");
members.add("Fushiguro Megumi");
System.out.println(members.get(0)); // Gojo Satoru
System.out.println(members.size()); // 3
members.remove("Gojo Satoru");
System.out.println(members.size()); // 2
HashMap
HashMap stores data as key-value pairs.
import java.util.HashMap;
HashMap<String, Integer> cursedEnergy = new HashMap<>();
cursedEnergy.put("Gojo Satoru", 9999);
cursedEnergy.put("Itadori Yuji", 500);
cursedEnergy.put("Fushiguro Megumi", 400);
System.out.println(cursedEnergy.get("Gojo Satoru")); // 9999
System.out.println(cursedEnergy.containsKey("Sukuna")); // false
For ArrayList, see ArrayList.add() / get(). For HashMap, see HashMap.put() / get().
Stream API
The Stream API (Java 8 and later) provides a way to process collections using a chain of filter, transform, and aggregate operations.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
List<String> members = Arrays.asList(
"Gojo Satoru", "Itadori Yuji", "Fushiguro Megumi",
"Kugisaki Nobara", "Ryomen Sukuna"
);
// Keep names longer than 12 characters, then convert to uppercase
List<String> result = members.stream()
.filter(name -> name.length() > 12)
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(result);
// [FUSHIGURO MEGUMI, KUGISAKI NOBARA, RYOMEN SUKUNA]
For more on the Stream API, see stream().filter() / map().
Exception Handling
Exception handling describes what to do when an error occurs during program execution. Java uses try-catch-finally.
try {
// Code that might throw an exception
int result = 10 / 0;
} catch (ArithmeticException e) {
// Runs if an exception is thrown
System.out.println("Error: " + e.getMessage()); // Error: / by zero
} finally {
// Always runs, regardless of whether an exception occurred
System.out.println("Done.");
}
For resources that must be closed after use (files, database connections, etc.), use try-with-resources.
import java.io.*;
// close() is called automatically when the try block ends
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("Read error: " + e.getMessage());
}
For more on exception handling, see try / catch / finally.
File I/O
From Java 11 onward, the Files class makes reading and writing files concise.
import java.io.IOException;
import java.nio.file.*;
// Write to a file (overwrites existing content)
try {
Files.writeString(Path.of("output.txt"), "Itadori Yuji, cursed energy: 9999");
System.out.println("Write complete.");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Read from a file
try {
String content = Files.readString(Path.of("output.txt"));
System.out.println(content); // Itadori Yuji, cursed energy: 9999
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
For file I/O, see Files.writeString() and Files.readString().
Generics
Generics provide a way to parameterize types. The same logic can be used safely with different types without duplicating code.
// <T> is a type parameter — the caller specifies the actual type
class Box<T> {
T value;
Box(T value) {
this.value = value;
}
T get() {
return value;
}
}
// A Box for String
Box<String> nameBox = new Box<>("Fushiguro Megumi");
System.out.println(nameBox.get()); // Fushiguro Megumi
// A Box for Integer
Box<Integer> powerBox = new Box<>(8500);
System.out.println(powerBox.get()); // 8500
The <> syntax in ArrayList<String> and HashMap<String, Integer> is generics in use. For more, see Generics.
Interfaces
An interface defines a set of methods that a class must implement. A class uses implements to declare that it satisfies the interface contract.
// Interface definition
interface Curseable {
// Any class implementing this interface must provide these methods
void activateCurse();
String getName();
}
// Class implementing the interface
class Sorcerer implements Curseable {
private String name;
Sorcerer(String name) {
this.name = name;
}
@Override
public void activateCurse() {
System.out.println(name + " used a cursed technique!");
}
@Override
public String getName() {
return name;
}
}
Curseable kugisaki = new Sorcerer("Kugisaki Nobara");
kugisaki.activateCurse(); // Kugisaki Nobara used a cursed technique!
Using interfaces allows you to write code that depends on a contract rather than a concrete implementation. For more, see interface / Abstract Class.
Asynchronous Processing — CompletableFuture
From Java 8 onward, CompletableFuture provides a way to write asynchronous code. Tasks run on separate threads in parallel, and follow-up steps can be chained to run after completion.
import java.util.concurrent.CompletableFuture;
// Run a task asynchronously (simulates an API call)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// Heavy work runs on a separate thread
return "Ryomen Sukuna";
});
// Chain steps to run after the result is ready
future.thenApply(name -> "Cursed King: " + name)
.thenAccept(System.out::println); // Cursed King: Ryomen Sukuna
// Block until the result is available and retrieve it
String result = future.join();
System.out.println(result); // Ryomen Sukuna
For more on CompletableFuture, see CompletableFuture.
Common Errors and How to Fix Them
NullPointerException
The most frequently encountered error. It occurs when a method is called on a null variable.
String name = null; System.out.println(name.length()); // NullPointerException!
// Fix: check for null before calling the method
String name = null;
if (name != null) {
System.out.println(name.length());
} else {
System.out.println("name is null");
}
ClassCastException
Occurs when an object is cast to an incompatible type.
Object obj = "Gojo Satoru"; Integer num = (Integer) obj; // ClassCastException!
// Fix: check the type with instanceof before casting
Object obj = "Gojo Satoru";
if (obj instanceof Integer) {
Integer num = (Integer) obj;
} else {
System.out.println("Not an Integer: " + obj.getClass().getName());
}
ArrayIndexOutOfBoundsException
Occurs when accessing an array at an index outside its bounds.
int[] scores = {100, 85, 92};
System.out.println(scores[3]); // ArrayIndexOutOfBoundsException!
// Fix: check the array length before accessing
int[] scores = {100, 85, 92};
int index = 3;
if (index < scores.length) {
System.out.println(scores[index]);
} else {
System.out.println("Index out of bounds");
}
Comparing Strings with ==
Using == on String compares references (memory addresses), not content.
String a = new String("Gojo Satoru");
String b = new String("Gojo Satoru");
System.out.println(a == b); // false (different references)
System.out.println(a.equals(b)); // true (same content)
Always use .equals() to compare string content.
Recommended Learning Order
A suggested path through the Java dictionary. There is no need to memorize everything at once — look up each page when you need it.
| Step | Topic | Pages |
|---|---|---|
| 1 | Setup and running files | Setup ↓ Running .java Files |
| 2 | Variables, types, and strings | String.length() / charAt() ↓ split() / join() |
| 3 | Classes and object-oriented programming | Class Definition / Constructor ↓ extends / Override |
| 4 | Collections | ArrayList ↓ HashMap |
| 5 | Exception handling | try / catch / finally |
| 6 | Stream API and lambda expressions | stream().filter() / map() ↓ Lambda Expressions |
| 7 | File I/O | Files.writeString() ↓ Files.readString() |
| 8 | Generics and interfaces | Generics ↓ interface / Abstract Class |
| 9 | Asynchronous processing | CompletableFuture |
Summary
The Big Picture
Java source code is written in .java files and compiled by javac into bytecode (.class files). Bytecode runs on the JVM, so the same program runs on any OS where a JVM is installed (Write Once, Run Anywhere).
Java is a statically typed object-oriented language. Type mismatches are caught at compile time. Classes hold fields and methods, and instances are created with new.
Key Features at a Glance
- Variables and types → Static typing. Primitive types (
int,boolean, etc.) and reference types (String, etc.). - Classes and objects → Defined with
class, instantiated withnew. Inheritance viaextends. - Collections →
ArrayList(dynamic list) /HashMap(key-value map). - Stream API →
.stream().filter().map().collect()for declarative collection processing. - Exception handling →
try-catch-finally/try-with-resources. - File I/O →
Files.writeString()/Files.readString()(Java 11 and later). - Generics →
<T>parameterizes types for type-safe reuse. - Interfaces →
interfacedefines a method contract;implementsfulfills it. - Asynchronous processing →
CompletableFuturefor parallel tasks and chained callbacks (Java 8 and later).
Common Errors
NullPointerException→ A method was called on anullvariable. Add anullcheck first.ClassCastException→ Cast to an incompatible type. Useinstanceofbefore casting.ArrayIndexOutOfBoundsException→ Accessed an array beyond its length. Check.lengthfirst.- String comparison with
==→ Compares references, not content. Use.equals()instead.
If you find any errors or copyright issues, please contact us.