Java Programming Complete Tutorial Study Guide

Java Programming Language Tutorial

Master Java programming from basic syntax to advanced Object-Oriented Programming (OOP), Collections Framework, Multithreading, and modern Java features with practical examples.

1. Introduction to Java

Java is a high-level, object-oriented programming language developed by Sun Microsystems (now Oracle). It follows the Write Once, Run Anywhere principle through the Java Virtual Machine (JVM).

  • Platform independent via bytecode and JVM
  • Strong typing with automatic memory management
  • Rich standard library and active ecosystem
  • Widely used in enterprise, Android, and backend systems
James Gosling, creator of the Java programming language

James Gosling

Father of Java — led the Oak project at Sun Microsystems

1995 — Java 1.0 JVM & bytecode WORA

James Gosling designed Java for portable, secure, object-oriented software. He led the Oak project, invented the JVM and bytecode model, and released Java publicly in 1995. Today Java powers enterprise servers, Android apps, and large-scale backend systems worldwide.

  • Originally called Oak; renamed Java for public release
  • Garbage collection and strong typing improve safety
  • Write Once, Run Anywhere through the Java Virtual Machine
Infographic of key Java features: platform independence, OOP, security, and rich APIs
Overview of the four pillars that make Java popular in industry and education.

Key Java features explained

1. Write Once, Run Anywhere (WORA)

Java source is compiled to bytecode (.class files), not machine code for one CPU. Any device with a Java Virtual Machine (JVM) can run that bytecode. You develop on Windows, deploy on Linux servers or Android devices, and the same compiled classes work without rewriting the program for each operating system.

2. Object-oriented programming (OOP)

Java is built around classes and objects. Real-world entities are modeled as types with data (fields) and behavior (methods). The four OOP principles in Java are:

  • Encapsulation — hide internal state with private fields and expose controlled access through methods.
  • Inheritance — reuse code with extends (e.g., Dog extends Animal).
  • Polymorphism — one interface, many implementations (method overriding and interfaces).
  • Abstraction — focus on what an object does, not how, using abstract classes and interfaces.

3. Secure and robust

Java catches many errors at compile time through static typing — you cannot assign a String to an int. The JVM provides a sandbox for applets and controlled execution. Garbage collection automatically frees unused objects, reducing memory leaks. Exception handling (try-catch-finally) lets programs recover from errors instead of crashing silently.

4. Rich standard library (APIs)

Java ships with thousands of classes in the JDK — no need to build everything from scratch:

  • java.util — collections (ArrayList, HashMap), dates, optional types.
  • java.io / java.nio — files, streams, and modern NIO for high-performance I/O.
  • java.net — sockets, HTTP clients, and networking.
  • java.util.concurrent — threads, executors, and concurrent collections.

Why teams choose Java

Large codebases stay maintainable thanks to strong typing, mature tooling (Maven, Gradle, IntelliJ), long-term support (LTS releases), and a huge job market in banking, Android, and enterprise backends.

Hello World
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

2. Java Syntax Basics

Every Java program is organized into classes. The entry point is the main method, and statements end with semicolons. Java is case-sensitive and uses curly braces to define blocks.

  • File name must match the public class name
  • Package declaration comes before imports
  • One public class per source file (convention)
  • Comments: // single-line, /* multi-line */
Diagram of Java program structure: package, import, class, fields, methods, and main
Java program structure: package declares the namespace (first line). import brings in classes from other packages. The class holds fields (data) and methods (behavior). public static void main(String[] args) is the program entry point.
Program structure
public class Demo {
    public static void main(String[] args) {
        int count = 10;
        System.out.println(count);
    }
}

3. Java vs Other Languages

Java is often compared to C++ (performance and systems heritage) and Python (ease of learning and rapid development). Each language makes different trade-offs: control vs safety, speed of development vs execution speed, and how code is compiled and run.

Aspect C++ Python Java
Paradigm Multi-paradigm (OOP, procedural, generic); manual memory Multi-paradigm; strong scripting / dynamic typing Primarily object-oriented; everything lives in a class
Typing Static, compile-time; pointers and references Dynamic; types checked at runtime Static, compile-time; no raw pointers in normal code
Compilation Compiled to native machine code per platform Interpreted (CPython) or bytecode (some implementations) Compiled to bytecode, then JVM JIT-compiles to native code
Memory Manual new / delete or smart pointers Automatic garbage collection (reference counting + GC) Automatic garbage collection in the JVM
Portability Recompile for each OS/CPU; platform-specific code common Interpreter must exist on target machine Bytecode + JVM — same .class on Windows, Linux, macOS
Performance Fastest for tight loops, games, embedded, OS-level work Slower for CPU-heavy numeric work; great for glue and scripts Strong for servers; JIT optimizes hot paths over time
Syntax / learning Complex (headers, templates, manual memory) Concise, readable; indentation matters Verbose but explicit; familiar C-style braces
Typical uses Games, drivers, browsers, high-frequency systems Data science, automation, web backends, teaching Enterprise apps, Android, banking, large backend services

C++ vs Java in practice

C++ gives you direct control over memory and hardware — ideal when every microsecond counts. Java trades some of that control for safety: no pointer arithmetic, no undefined behavior from dangling pointers, and a single portable binary format (bytecode). A C++ program compiled on Windows will not run on Linux without rebuilding; a Java .jar runs wherever a JVM is installed.

Python vs Java in practice

Python lets you write fewer lines and experiment quickly — perfect for scripts, notebooks, and prototypes. Java requires more boilerplate but catches type errors before you run the program, which matters in teams with millions of lines of code. For long-running server applications processing heavy workloads, Java’s JVM optimizations often outperform CPython.

Same idea in three languages
// Java — static typing; error at compile time
int age = 25;
// age = "twenty";  // compile error

String name = "Java";
System.out.println(name.toUpperCase());

// Python equivalent (conceptual):
// age = 25
// age = "twenty"   # allowed at runtime
// name = "java"
// print(name.upper())

// C++ equivalent (conceptual):
// int age = 25;
// std::string name = "Java";
// std::cout << name;

4. Compiling and Running Java

Unlike C++, which compiles directly to machine code for one platform, Java uses a two-step process: compile to bytecode, then run on a JVM. That separation is what makes Java portable.

Diagram of Java program execution: source code, javac compiler, bytecode, and JVM
End-to-end flow from source file to running program on any operating system with a JVM.

How Java runs — step by step

Step 1: Write source code

You create a text file such as HelloWorld.java containing a public class and a main method. The file name must match the public class name.

Step 2: Compile with javac

The Java compiler (javac) checks syntax and types, then produces one or more .class files containing bytecode — a platform-neutral instruction set for the JVM. If you have errors (missing semicolon, wrong type), compilation fails and no .class file is produced.

Step 3: Load and verify bytecode

When you run java HelloWorld, the JVM class loader finds HelloWorld.class, loads it into memory, and the bytecode verifier checks that the code is safe (no illegal memory access, valid jumps). This is part of Java’s security model.

Step 4: Execute — interpreter and JIT

The JVM starts by interpreting bytecode line by line. Frequently executed code paths are identified and compiled to native machine code by the Just-In-Time (JIT) compiler for faster performance. So Java is not “only interpreted” — hot code runs as fast as optimized native code after warm-up.

Step 5: Garbage collection

While your program runs, the JVM tracks objects on the heap. When objects are no longer reachable, the garbage collector reclaims memory automatically — you do not call free as in C++.

Tool / concept Role
javacCompiler — turns .java into .class bytecode
javaLauncher — starts the JVM and calls main
CLASSPATHTells the JVM where to search for classes and JARs
.jarArchive of many .class files + metadata for deployment
JVMRuns bytecode; includes loader, verifier, JIT, and GC
Terminal example: After saving HelloWorld.java, run javac HelloWorld.java then java HelloWorld. IDEs (IntelliJ, Eclipse, VS Code) run these steps for you when you click Run.
Compile and run
// Terminal:
//   javac HelloWorld.java    → creates HelloWorld.class
//   java HelloWorld          → JVM runs main()

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Running on JVM");
        System.out.println("Java version: " + System.getProperty("java.version"));
    }
}

5. Variables and Data Types

A variable is a named container for data. In Java you must declare the type before the name: int count = 10;. Types fall into two groups: primitives (built-in values) and reference types (objects on the heap).

Diagram of Java data types: primitives and reference types
Primitives hold values directly; reference variables point to objects such as String and arrays.

Primitive data types

Primitives store simple values. They are not objects and do not support methods (except wrapper classes like Integer when you need them).

Type Size (typical) Example value Use case
byte8 bit-128 to 127Binary data, small counters
short16 bit32000Legacy / compact numeric data
int32 bit42Default for integers (counts, indexes)
long64 bit9_223_372_036_854_775_807LLarge numbers (timestamps)
float32 bit3.14fApproximate decimals (suffix f)
double64 bit19.99Default for decimals (money, science)
char16 bit Unicode'A'Single character (single quotes)
boolean1 bit (JVM)true / falseConditions and flags

Reference data types

Classes, interfaces, arrays, and String are reference types. The variable stores a reference (address) to an object on the heap; the object can be large and shared.

  • String name = "Nikhil"; — text (immutable)
  • int[] scores = {90, 85, 88}; — array of primitives
  • Scanner input = new Scanner(System.in); — object instance

Constants with final

Use final when a variable must not be reassigned after initialization. By convention, constant names use UPPER_SNAKE_CASE.

Primitives, references, and final
public class DataTypesDemo {
    public static void main(String[] args) {
        // Primitives
        int age = 21;
        long worldPopulation = 8_100_000_000L;
        double price = 19.99;
        float taxRate = 0.18f;
        char grade = 'A';
        boolean isStudent = true;

        // Reference types
        String city = "Hyderabad";
        int[] marks = {78, 92, 85};
        String[] subjects = {"Java", "Math", "Physics"};

        // Constants
        final double PI = 3.14159;
        final int MAX_LOGIN_ATTEMPTS = 3;
        // PI = 3.14;  // compile error — cannot reassign final

        // Using variables
        System.out.println(city + " — age " + age + ", grade " + grade);
        System.out.println("First mark: " + marks[0]);
        System.out.println("Subjects: " + subjects[1]);

        // Wrapper classes (primitive → object when needed)
        Integer boxedAge = age;           // autoboxing
        int unboxed = boxedAge;           // unboxing
        System.out.println("Boxed age: " + boxedAge);
    }
}
Type conversion: Assigning a int to a long is widening (automatic). Putting a double into an int requires an explicit cast: int n = (int) 9.7;9.