Java

Official Documentation for Java

Loops

For loops:

// Syntax for iterating over a range of numbers:
for (int i = 0; i < 5; i++) {
    // Code block executed for each iteration
}

// Syntax for iterating over elements in an array or list:
for (int i = 0; i < array.length; i++) {
    // Code block executed for each element
}

While loops:

// Syntax for a while loop:
while (condition) {
    // Code block executed as long as the condition is true
}

Do-while loops:

// Syntax for a do-while loop (the body runs at least once):
do {
    // Code block executed for each iteration
} while (condition);

Enhanced for loops:

// Syntax for iterating over elements in an array or collection:
for (String item : collection) {
    // Code block executed for each element
}

Variable Assignment

// Syntax for variable assignment (explicit type):
DataType variableName = value;

// Syntax for variable assignment (type inference with var, Java 10+):
var variableName = value;

Functions

In Java, functions are defined as methods inside a class.

// Syntax for defining a method:
returnType methodName(DataType parameter1, DataType parameter2) {
    // Code block defining the method's behavior
    return result;
}

Classes

// Syntax for defining a class:
public class ClassName {
    // Fields (instance variables):
    private DataType fieldName;

    // Constructor:
    public ClassName(DataType fieldName) {
        this.fieldName = fieldName;
    }

    // Method:
    public returnType methodName(DataType parameter) {
        // Code block defining the method's behavior
        return result;
    }
}

// Creating an instance and calling a method:
ClassName instance = new ClassName(value);
instance.methodName(argument);

Inheritance

A class inherits from another class with extends. The subclass gets the superclass’s fields and methods, and can add to or override them.

// Superclass:
public class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    public String speak() {
        return "...";
    }
}

// Subclass:
public class Dog extends Animal {
    public Dog(String name) {
        super(name);  // Calls the superclass constructor
    }

    @Override
    public String speak() {
        return "Woof!";
    }
}

Notes:

Polymorphism

Polymorphism lets a supertype reference hold a subtype instance and dispatch to that instance’s overridden method at runtime. This dynamic dispatch works the same way through interfaces.

import java.util.List;

// A supertype reference can point at a subtype instance:
Animal myDog = new Dog("Rex");
System.out.println(myDog.speak());  // Output: Woof!

// The call resolves to each object's own implementation.
// (Cat is another Animal subclass that overrides speak() to return "Meow!")
List<Animal> animals = List.of(new Dog("Rex"), new Cat("Mittens"));
for (Animal animal : animals) {
    System.out.println(animal.speak());  // Output: Woof!, then Meow!
}

Interfaces are the usual way to program against a type without depending on a concrete class:

public interface Shape {
    double area();
}

public class Circle implements Shape {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

// Any Shape works, regardless of its concrete class:
Shape shape = new Circle(2.0);
System.out.println(shape.area());  // Output: 12.566370614359172

Method overloading is the other flavor. It is resolved at compile time by parameter types, rather than at runtime:

// Overloaded methods share a name but differ in their parameters:
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }
}

Overriding requires the same signature and is resolved at runtime; overloading uses different parameter lists and is resolved at compile time.

Program Entry Point

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

A single-file program can be run directly without a separate compile step (Java 11+):

java Main.java

String Interpolation

Java has no built-in string interpolation. Use concatenation, String.format, or formatted (Java 15+).

// Syntax for string interpolation using concatenation:
String variable = "world";
String message = "Hello, " + variable + "!";
System.out.println(message);  // Output: Hello, world!

// Or using String.format:
String formatted = String.format("Hello, %s!", variable);
System.out.println(formatted);  // Output: Hello, world!

// Or using formatted (Java 15+):
String text = "Hello, %s!".formatted(variable);
System.out.println(text);  // Output: Hello, world!

Multiline Strings

Text blocks (Java 15+):

// Syntax for multiline strings using a text block:
String multilineString = """
        This is a multiline string.
        It can span multiple lines.
        """;

Older style using concatenation and newline escapes:

// Syntax for multiline strings using concatenation:
String multilineString = "This is a multiline string.\n" +
        "It can span multiple lines.";

File I/O

import java.nio.file.Files;
import java.nio.file.Path;

// Reading from a file:
String content = Files.readString(Path.of("filename.txt"));

// Writing to a file:
Files.writeString(Path.of("output.txt"), "Hello, world!");

HTTP Requests

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.example.com/data"))
        .GET()
        .build();

try {
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    String data = response.body();
    // Process the data
} catch (IOException | InterruptedException e) {
    // Handle error
}

Arrays

import java.util.Arrays;

// Creating an array:
int[] myArray = {1, 2, 3, 4, 5};

// Accessing elements:
System.out.println(myArray[0]);  // Output: 1

// Slicing (arrays are fixed size, so this makes a copy):
int[] slice = Arrays.copyOfRange(myArray, 1, 4);
System.out.println(Arrays.toString(slice));  // Output: [2, 3, 4]

// Modifying elements:
myArray[2] = 10;
System.out.println(myArray[2]);  // Output: 10

// Arrays have a fixed length and cannot grow; use a List to append elements.

Lists

import java.util.ArrayList;
import java.util.List;

// Creating a list:
List<Integer> myList = new ArrayList<>(List.of(1, 2, 3, 4, 5));

// Accessing elements:
System.out.println(myList.get(0));  // Output: 1

// Slicing:
System.out.println(myList.subList(1, 4));  // Output: [2, 3, 4]

// Modifying elements:
myList.set(2, 10);
System.out.println(myList);  // Output: [1, 2, 10, 4, 5]

// Appending elements:
myList.add(6);
System.out.println(myList);  // Output: [1, 2, 10, 4, 5, 6]

Maps (Dictionaries)

LinkedHashMap preserves insertion order. HashMap does not guarantee any order.

import java.util.LinkedHashMap;
import java.util.Map;

// Creating a map:
Map<String, Object> myMap = new LinkedHashMap<>();
myMap.put("name", "John");
myMap.put("age", 30);
myMap.put("city", "New York");

// Accessing elements:
System.out.println(myMap.get("name"));  // Output: John

// Modifying elements:
myMap.put("age", 35);
System.out.println(myMap);  // Output: {name=John, age=35, city=New York}

// Adding new key-value pairs:
myMap.put("occupation", "Engineer");
System.out.println(myMap);  // Output: {name=John, age=35, city=New York, occupation=Engineer}