Java Tooling & Next Steps

Build tools

Compiling by hand stops working as soon as you have dependencies. Use Maven or Gradle.

Maven — pom.xml, declarative, ubiquitous:

XML
<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>
Bash
mvn compile
mvn test
mvn package        # builds a jar

Gradle — build.gradle, more concise, the Android standard:

GROOVY
dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

Testing with JUnit

Java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    @Test
    void addsTwoNumbers() {
        assertEquals(7, Calculator.add(3, 4));
    }

    @Test
    void rejectsNegativeDeposit() {
        Account a = new Account();
        assertThrows(IllegalArgumentException.class, () -> a.deposit(-5));
    }
}

Test the logic that would be expensive to get wrong — pricing, validation, date handling — rather than chasing a coverage number.

Project layout

Code
src/
  main/java/com/example/App.java
  main/resources/
  test/java/com/example/AppTest.java
pom.xml

Package names follow reverse domain order: com.example.project.

Where to go next

Spring Boot — the dominant Java backend framework. Dependency injection, REST endpoints, database access, and security with very little boilerplate.

JDBC / JPA / Hibernate — talking to databases. Learn plain JDBC with PreparedStatement first so you understand what an ORM is doing for you (and, as in every language, never concatenate user input into SQL).

Kotlin — runs on the same JVM, interoperates with all Java libraries, and removes much of Java's verbosity. The default for new Android work.

Modern Java features — if you learned Java 8, look at records, sealed classes, pattern matching for switch, text blocks, and virtual threads (Java 21). The language has changed considerably.

Habits worth forming

  • Prefer immutability: final fields, records, List.of().
  • Program to interfaces (List, not ArrayList) in declarations.
  • Return empty collections, never null.
  • Use Optional for "might not exist" return values.
  • Write @Override every time you override.
  • Keep methods short and named for what they do.
  • Let exceptions travel to a layer that can actually handle them.