cv.cm

Coding · Programming languages

Java tutorial for beginners

7 min read

Short answer

Java is a statically typed, object-oriented language that compiles to bytecode and runs on the Java Virtual Machine (JVM) on any operating system. Install a JDK, save a class in Hello.java and run java Hello.java. The core ideas are classes and objects, primitive and reference types, the collections framework (List, Map, Set), checked exceptions, and newer features such as records, var and pattern matching.

Open Regex tester

What Java is and what it is used for

Java was released by Sun Microsystems in 1995 and is now developed in the open OpenJDK project, with Oracle as the main steward. Its promise is "write once, run anywhere": the compiler produces bytecode, and the JVM runs it on Windows, macOS and Linux. Java is used for large business back ends (often with Spring Boot), Android apps (alongside Kotlin), big-data tools such as Apache Kafka and Hadoop, and many desktop and embedded systems. A new version comes out every six months, and long-term support (LTS) versions such as Java 21 are the usual choice for production.

Install a JDK and run Hello, world

Install a JDK (Java Development Kit), for example an OpenJDK build such as Eclipse Temurin or Oracle's JDK. Check it with java -version. Every Java program lives in a class, and execution starts at main.

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, world");
    }
}
java Hello.java        # run a single source file directly
# Hello, world
javac Hello.java       # or compile to Hello.class first
java Hello

The file name must match the public class name (Hello.java for class Hello).

Variables and basic types

Java has eight primitive types, stored directly as values, and reference types (objects such as String and arrays). Every variable has a fixed type; var lets the compiler infer it from the initial value inside methods.

TypeSizeExample
int32-bitint n = 42;
long64-bitlong big = 10_000_000_000L;
double64-bit floatdouble pi = 3.14159;
booleantrue/falseboolean ok = true;
char16-bit UTF-16 unitchar c = 'A';
byte, short, float8, 16, 32-bitUsed less often
StringreferenceString s = "hi";
int count = 7;
double avg = count / 2;          // 3.0, integer division happens first
double avg2 = count / 2.0;       // 3.5
var name = "Ada";                // inferred as String
String msg = name + " has " + count + " items";
System.out.println(msg);         // Ada has 7 items
System.out.println(Integer.parseInt("12") + 1); // 13

This is a fragment: place statements like these inside a method such as main.

Control flow

int score = 72;
if (score >= 90) {
    System.out.println("A");
} else if (score >= 70) {
    System.out.println("B");     // B
} else {
    System.out.println("C");
}
for (int i = 0; i < 3; i++) {
    System.out.println(i);       // 0, 1, 2
}
String day = "SAT";
String kind = switch (day) {     // switch expression
    case "SAT", "SUN" -> "weekend";
    default -> "weekday";
};
System.out.println(kind);        // weekend

Java also has while, do/while, and the enhanced for (String s : list) loop for iterating over arrays and collections.

Methods, classes and records

A class bundles fields (data) and methods (behavior). static methods belong to the class itself; other methods are called on an object created with new. A record is a short way to declare an immutable data class: the compiler generates the constructor, accessors, equals, hashCode and toString.

public class Shapes {
    static double square(double x) {
        return x * x;
    }
    static class Counter {
        private int value;
        void increment() { value++; }
        int get() { return value; }
    }
    record Point(int x, int y) {
        double distance() { return Math.sqrt(x * x + y * y); }
    }
    public static void main(String[] args) {
        System.out.println(square(4));        // 16.0
        Counter c = new Counter();
        c.increment();
        c.increment();
        System.out.println(c.get());          // 2
        Point p = new Point(3, 4);
        System.out.println(p + " " + p.distance()); // Point[x=3, y=4] 5.0
    }
}

Classes can extend one parent class (extends) and implement many interfaces (implements). Fields are usually private, with access through methods.

Collections: List, Map and Set

The collections framework in java.util provides resizable data structures. Collections hold objects, so primitives are boxed automatically (int becomes Integer).

import java.util.*;
public class Collections101 {
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>(List.of(3, 1, 2));
        nums.add(5);
        Collections.sort(nums);
        System.out.println(nums + " " + nums.get(0));  // [1, 2, 3, 5] 1
        Map<String, Integer> ages = new HashMap<>();
        ages.put("ann", 31);
        ages.put("bob", 25);
        System.out.println(ages.getOrDefault("zed", 0)); // 0
        Set<String> tags = new TreeSet<>(List.of("b", "a", "b"));
        System.out.println(tags);                        // [a, b]
        List<Integer> evensSquared = nums.stream()
            .filter(n -> n % 2 == 0)
            .map(n -> n * n)
            .toList();
        System.out.println(evensSquared);                // [4]
    }
}

The last statement uses streams and lambdas, a functional style for transforming collections. List.of creates an immutable list; wrap it in new ArrayList<>(...) when you need to change it.

Signature features: static typing, interfaces and pattern matching

Interfaces define a contract that many classes can implement, which is the basis of most Java design. Modern Java adds pattern matching: instanceof and switch can test a type and bind a variable in one step. Sealed interfaces (Java 17 and later) list every allowed implementation, so the compiler can check that a switch covers all cases.

public class Areas {
    sealed interface Shape permits Circle, Rect {}
    record Circle(double r) implements Shape {}
    record Rect(double w, double h) implements Shape {}
    static double area(Shape s) {
        return switch (s) {
            case Circle c -> Math.PI * c.r() * c.r();
            case Rect r -> r.w() * r.h();
        };
    }
    public static void main(String[] args) {
        System.out.println(area(new Rect(2, 3)));  // 6.0
    }
}

Pattern matching for switch like this is standard in Java 21 LTS and later.

Exceptions

Errors are exceptions. Checked exceptions (such as IOException) must be caught or declared with throws; unchecked ones (subclasses of RuntimeException, such as NullPointerException) need not be. try-with-resources closes files and connections automatically.

import java.io.*;
import java.nio.file.*;
public class ReadFirst {
    static int parseAge(String text) {
        int age = Integer.parseInt(text);   // may throw NumberFormatException
        if (age < 0) throw new IllegalArgumentException("negative age");
        return age;
    }
    public static void main(String[] args) {
        try {
            System.out.println(parseAge("abc"));
        } catch (NumberFormatException e) {
            System.out.println("not a number");  // not a number
        }
        try (BufferedReader in = Files.newBufferedReader(Path.of("notes.txt"))) {
            System.out.println(in.readLine());
        } catch (IOException e) {
            System.out.println("cannot read: " + e.getMessage());
        }
    }
}

A small complete program: word counter

import java.io.IOException;
import java.nio.file.*;
import java.util.*;
public class WordCount {
    public static void main(String[] args) throws IOException {
        if (args.length != 1) {
            System.err.println("usage: java WordCount.java FILE");
            System.exit(1);
        }
        String text = Files.readString(Path.of(args[0])).toLowerCase();
        Map<String, Integer> counts = new HashMap<>();
        for (String word : text.split("[^a-z']+")) {
            if (!word.isEmpty()) counts.merge(word, 1, Integer::sum);
        }
        counts.entrySet().stream()
            .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
            .limit(5)
            .forEach(e -> System.out.printf("%5d  %s%n", e.getValue(), e.getKey()));
    }
}

Run it with java WordCount.java notes.txt. It prints the five most common words with their counts.

Common beginner mistakes

  • Integer division: 5 / 2 is 2. Make one side a double to get 2.5.
  • NullPointerException from calling a method on null. Check for null, or use Optional for values that may be missing.
  • Trying to change a list created with List.of, which throws UnsupportedOperationException.
  • Forgetting that array and List indexes start at 0, so the last element is at length - 1.

Where to go next

Follow the learning paths on dev.java, the official Java developer site, and keep the Java SE API documentation open as a reference. Learn a build tool (Maven or Gradle), unit testing with JUnit, and then a framework such as Spring Boot for web services. Kotlin, which also runs on the JVM, is a natural next language.

FAQ

Is Java hard to learn?

Java is more verbose than Python, because you declare types and put code in classes, but its rules are consistent and the compiler explains mistakes early. Many universities use it as a first language.

What is the difference between the JDK and the JVM?

The JVM runs compiled bytecode. The JDK is the full development kit: the JVM plus the compiler javac, the standard library and tools. Developers install the JDK.

Which Java version should I learn?

Learn a current long-term support version, such as Java 21 or a newer LTS. Older code still runs on new JVMs, so modern skills also apply to existing projects.

Is Java the same as JavaScript?

No. Despite the similar names, they are separate languages with different type systems, runtimes and uses.

Is Java still used?

Yes. It remains one of the most used languages for enterprise back ends, Android and data infrastructure.

All coding tutorials