Java Introduction
What Java Is
Java is a general-purpose, object-oriented programming language that runs on a virtual machine. You write source code in .java files, a compiler translates that code into an intermediate form called bytecode, and a program called the Java Virtual Machine (JVM) executes the bytecode on whatever operating system it is installed on.
That single design decision, compiling to bytecode instead of directly to machine code, is the reason behind Java's most famous promise: write once, run anywhere. The same compiled .class file runs on Windows, Linux, and macOS without recompilation, because the JVM on each platform handles the translation to that platform's native instructions.
Java was created at Sun Microsystems in the mid-1990s and is now developed by Oracle together with the OpenJDK community. It is one of the most widely deployed languages in the world, especially for server-side systems, enterprise applications, Android development, and large-scale data processing.
How a Java Program Runs
Understanding the execution pipeline early makes almost everything else in Java easier to reason about, because many language rules exist specifically because of this pipeline.
HelloWorld.java ---> javac (compiler) ---> HelloWorld.class ---> java (JVM) ---> running program
source code bytecode
Step 1: Source code
You write human-readable code in a file whose name ends in .java. The file name must match the public class it contains. If the class is called HelloWorld, the file must be HelloWorld.java. This is not a style convention; the compiler enforces it so that the JVM can locate classes by name at runtime.
Step 2: Compilation to bytecode
The javac command reads the .java file, checks it for errors (syntax errors, type errors, missing semicolons, undefined variables), and produces a .class file. The .class file does not contain machine code for your CPU. It contains bytecode, a compact instruction set designed for the JVM rather than for Intel, ARM, or any other hardware.
If the compiler finds an error, no .class file is produced. This is why Java is described as a statically typed, compiled language: many categories of mistakes are caught before the program ever runs.
Step 3: Execution on the JVM
The java command starts a JVM, loads the .class file, verifies that the bytecode is safe, and then executes it. Modern JVMs do not simply interpret bytecode line by line. They use a Just-In-Time (JIT) compiler that watches which parts of the program run frequently and compiles those hot sections into optimized native machine code while the program is running. This is why long-running Java applications are often very fast despite the extra abstraction layer.
Your First Java Program
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Save this as HelloWorld.java, then compile and run it from a terminal:
javac HelloWorld.java
java HelloWorld
Output:
Hello, World!
Line-by-line explanation
public class HelloWorld {
Every piece of executable Java code lives inside a class. There are no free-floating functions as in C or Python scripts. class declares a new class, HelloWorld is its name, and public means the class is visible to code outside its own package. The opening brace { begins the class body.
The class name uses PascalCase (each word capitalized). The compiler does not require this, but the entire Java ecosystem follows it, and tooling, frameworks, and other developers expect it.
public static void main(String[] args) {
This is the entry point. When you run java HelloWorld, the JVM looks for a method with exactly this signature and starts executing there. Each word has a purpose:
| Part | Meaning | Why it is required |
|---|---|---|
public | The method can be called from anywhere | The JVM is outside your class and must be able to call it |
static | The method belongs to the class, not to an object | The JVM calls main before any object exists, so it cannot be an instance method |
void | The method returns nothing | The JVM does not use a return value; exit codes are set differently |
main | The method name | The JVM looks for this exact name |
String[] args | An array of command-line arguments | Lets the program receive input such as java HelloWorld Alice |
If you change any part of this signature, for example writing static void main() without public or without the String[] parameter, the program compiles but the JVM reports that it cannot find the main method.
System.out.println("Hello, World!");
System is a built-in class that represents the running system. out is a field inside it that refers to the standard output stream (normally your terminal). println is a method on that stream that prints the text and then moves to a new line. The text inside double quotes is a String literal.
The semicolon ends the statement. In Java, every statement must end with a semicolon; line breaks carry no meaning to the compiler.
The closing braces }
The first } closes the main method; the second closes the class. Every opening brace must have a matching closing brace.
Running with command-line arguments
The args parameter is rarely used in a first program, but it demonstrates how a Java program receives input from outside:
public class Greeter {
public static void main(String[] args) {
if (args.length > 0) {
System.out.println("Hello, " + args[0] + "!");
} else {
System.out.println("Hello, stranger!");
}
}
}
javac Greeter.java
java Greeter Alice
Output:
Hello, Alice!
Running java Greeter with no argument prints Hello, stranger!. The args.length check prevents an ArrayIndexOutOfBoundsException, which would occur if the code tried to read args[0] from an empty array.
Running a Single File Without Explicit Compilation
Since JDK 11, you can run a single-file program directly without a separate javac step:
java HelloWorld.java
The java launcher compiles the file in memory and runs it immediately. No .class file is written to disk. This is convenient for learning and for small scripts, but larger projects still use the explicit compile step (usually driven by a build tool) because they involve many files and dependencies.
The Platform: JDK, JRE, and JVM
These three terms are used constantly and are easy to mix up.
| Term | What it is | Who needs it |
|---|---|---|
| JVM (Java Virtual Machine) | The program that executes bytecode | Anyone running Java software |
| JRE (Java Runtime Environment) | The JVM plus the standard class library (String, ArrayList, System, and thousands more) | Anyone running Java software |
| JDK (Java Development Kit) | The JRE plus development tools: javac, jar, javadoc, jshell, debuggers, profilers | Anyone writing Java software |
As a developer you install the JDK. It contains everything needed to both compile and run programs. Since JDK 11, Oracle and most vendors no longer distribute a standalone JRE; the JDK is the standard download.
Java Editions
Java is not a single product. There are several editions aimed at different environments.
Java SE (Standard Edition) is the core platform: the language, the JVM, and the standard library covering collections, I/O, networking, concurrency, and more. Everything in a typical Java tutorial, including this one, is Java SE.
Jakarta EE (formerly Java EE, Enterprise Edition) is a set of specifications built on top of Java SE for large server-side applications: servlets, REST APIs, persistence, messaging, dependency injection. It was transferred from Oracle to the Eclipse Foundation and renamed from javax.* to jakarta.* packages. Frameworks such as Spring are not Jakarta EE themselves but build on many of the same ideas.
Java ME (Micro Edition) targets small embedded and mobile devices. It is far less common today.
Android uses the Java language (alongside Kotlin) but runs on its own runtime (ART) rather than a standard JVM, and its class library differs in places from Java SE.
Java Versions and Release Cadence
Java moved to a time-based release schedule in 2017. A new feature release ships every six months, in March and September. Every two years one of those releases is designated Long-Term Support (LTS) and receives updates for many years. Non-LTS releases are supported only until the next release.
Recent LTS releases are Java 11, 17, 21, and 25. Most production systems run on an LTS version, and most libraries target the LTS versions. When starting new work, install the latest LTS unless you have a specific reason not to. Many modern language features used in this tutorial, such as records, text blocks, switch expressions, pattern matching, and virtual threads, were introduced across Java 14 through 21, so a current LTS is assumed throughout.
You can check the installed version with:
java -version
Example output:
openjdk version "25" 2025-09-16
OpenJDK Runtime Environment (build 25+36)
OpenJDK 64-Bit Server VM (build 25+36, mixed mode, sharing)
The first line is the important one: it tells you which Java version the java command will use.
OpenJDK and Vendor Distributions
The Java platform is developed as an open-source project called OpenJDK. Multiple organizations build and distribute binaries from that same source:
- Oracle JDK (Oracle)
- Eclipse Temurin (Adoptium, Eclipse Foundation)
- Amazon Corretto
- Microsoft Build of OpenJDK
- Azul Zulu
- Red Hat build of OpenJDK
These are functionally the same Java. The differences are in licensing, support contracts, and update schedules. For learning and for most development, any of them is fine. Eclipse Temurin is a common default because it is free for all uses and widely packaged.
Where Java Is Used
Knowing where a language is used helps explain why it was designed the way it was.
Backend and enterprise systems. Banks, insurers, airlines, and large e-commerce platforms run enormous Java codebases. The language's static typing, mature tooling, and long-term backward compatibility make it suitable for systems that must be maintained for decades. Spring Boot is the dominant framework in this space.
Android applications. Android's original development language was Java, and a very large share of Android code is still Java even as Kotlin has become the recommended language.
Big data and distributed systems. Apache Hadoop, Apache Kafka, Apache Spark (whose core is Scala, which also runs on the JVM), Elasticsearch, and Cassandra are all JVM-based. The JVM's performance under sustained load and its mature concurrency libraries are major reasons for this.
Developer tooling. IntelliJ IDEA, Eclipse, Jenkins, Maven, and Gradle are themselves written in Java or other JVM languages.
Desktop applications. Less common than it once was, but still used through JavaFX and Swing.
Why Learn Java Specifically
Beyond the job market, Java teaches concepts that transfer directly to other languages. Its object-oriented model is explicit rather than implicit, so classes, interfaces, inheritance, and polymorphism are visible in the syntax and easier to learn than in languages where they are hidden. Its static type system makes the relationship between types and operations concrete. Its memory model, with automatic garbage collection, lets you focus on logic while still exposing you to concepts such as references versus values that matter in every language.
Languages such as C#, Kotlin, Scala, and even TypeScript borrow heavily from Java's design, so time spent understanding Java pays off well beyond Java itself.
Java Compared to Similar Languages
| Aspect | Java | Python | C++ | JavaScript |
|---|---|---|---|---|
| Typing | Static, strong | Dynamic, strong | Static, weaker | Dynamic, weak |
| Compilation | To bytecode, then JIT | Interpreted (bytecode cached) | To native machine code | JIT in the browser or Node.js |
| Memory management | Automatic (garbage collector) | Automatic | Manual (with RAII and smart pointers) | Automatic |
| Primary paradigm | Object-oriented, with functional features | Multi-paradigm | Multi-paradigm | Multi-paradigm, prototype-based |
| Typical use | Backend, Android, enterprise, big data | Scripting, data science, automation | Systems, games, performance-critical code | Web frontends, Node.js backends |
| Execution model | Runs on the JVM | Runs on the Python interpreter | Runs directly on hardware | Runs on a JavaScript engine |
Static typing means every variable has a type known at compile time. You declare int count = 5; rather than just count = 5. This is more verbose than Python but catches a large category of bugs before the program runs and makes large codebases far easier to refactor, because tools can trace exactly where every variable and method is used.