
Java
First appeared 1995 · James Gosling
The enterprise workhorse — thirty years old, still runs a large share of the world's back ends.
Overview
Java is a high-level, class-based, object-oriented programming language designed to have as few implementation dependencies as possible. Developed in the early 1990s by James Gosling and his team at Sun Microsystems, Java has become one of the most widely adopted programming languages globally. It emphasizes portability, scalability, and maintainability, making it a top choice for enterprise applications, Android development, cloud computing, and server-side systems. Java is compiled into bytecode that runs on the Java Virtual Machine (JVM), allowing the same code to run on multiple platforms without modification. Its rich standard library includes tools for data structures, networking, concurrency, and GUI development. Java supports multiple programming paradigms, including object-oriented, functional, and concurrent programming. Its ecosystem is vast, with frameworks such as Spring, Hibernate, and Jakarta EE enabling developers to build robust, scalable, and secure applications. Over decades, Java has influenced numerous modern programming languages and continues to be a core technology in many software development environments, thanks to its reliability, strong typing, and community support.
Key facts
The reference details, without the paragraph.
- First appeared
- 1995
- Designed by
- James Gosling at Sun Microsystems
- Typing
- Static, strong and nominal, with type inference for local variables (`var`)
- Execution
- Compiled to bytecode, run on the JVM with a just-in-time compiler
- Memory model
- Automatic — generational garbage collection (G1, ZGC, Shenandoah)
- Package manager
- Maven or Gradle, backed by Maven Central
- File extensions
- .java, .class, .jar
- Current LTS
- Java 21 (2023) and Java 25 (2025)
- Release cadence
- A feature release every six months, an LTS every two years
- Licence
- OpenJDK is GPLv2 with the Classpath Exception
History
How the language got here — the decisions that still shape how you write it.
Java was created by James Gosling, Mike Sheridan, and Patrick Naughton at Sun Microsystems in 1991 as part of the Green Project, initially intended for interactive television and embedded systems. The project evolved into a general-purpose programming language emphasizing portability and cross-platform compatibility. Released publicly in 1995, Java introduced the revolutionary concept of 'Write Once, Run Anywhere' through the Java Virtual Machine (JVM), allowing programs to execute on any platform with a compatible JVM. Java quickly gained popularity in the enterprise software world, powering web applications, banking systems, and large-scale corporate software. Its evolution over time includes the addition of generics, lambda expressions, streams, modularization, and enhanced memory management, keeping the language modern while retaining backward compatibility. Java’s syntax draws heavily from C and C++, offering familiarity while abstracting low-level complexities. The language emphasizes robustness, security, and maintainability, features critical for large-scale software systems. Java’s extensive ecosystem, including tools, libraries, frameworks, and integrated development environments (IDEs) like IntelliJ IDEA and Eclipse, has cemented its position as a staple in software development. Open-source initiatives, active community engagement, and regular updates ensure Java remains relevant in modern computing contexts, from server-side applications to cloud-native solutions and Android development. The Java community organizes conferences such as JavaOne and maintains extensive documentation and tutorials, making it accessible to learners and professionals alike. Java’s influence extends beyond programming languages; it has shaped software engineering practices, design patterns, and development methodologies. Its combination of portability, scalability, and reliability has made it a cornerstone of the programming world for decades.
- 1991
The Green Project
James Gosling starts work on a language for interactive television set-top boxes at Sun. It is called Oak, after a tree outside his office. The television market never materialises.
- 1995
Write once, run anywhere
Java launches aimed at the web, with applets running inside Netscape. The applets are forgotten; the promise of portable bytecode running on any JVM turns out to be the durable idea.
- 1998
Java 2 and the enterprise
The platform splits into editions and gains Swing and the Collections Framework. Java becomes the default choice for business software.
- 2004
Java 5 modernises the language
Generics, annotations, enums, autoboxing and the enhanced `for` loop arrive together — arguably the largest single upgrade in Java's history.
- 2010
Oracle acquires Sun
Stewardship passes to Oracle, triggering years of licensing anxiety that ultimately push the ecosystem toward OpenJDK builds as the norm.
- 2014
Java 8 — lambdas and streams
Functional-style programming arrives, along with `Optional` and a sane date-time API. Java 8 becomes the most widely deployed version in history and stays that way for a decade.
- 2017
Six-month releases
Java moves from multi-year mega-releases to a predictable cadence, with long-term-support versions every few years. Features ship when ready instead of holding up a release.
- 2021
Records, sealed types and pattern matching
Java 17 lands a set of features aimed squarely at boilerplate — data carriers in one line, closed type hierarchies, and `switch` that can destructure.
- 2023
Virtual threads
Java 21 ships Project Loom's virtual threads: millions of cheap threads that make straightforward blocking code scale like asynchronous code. It removes much of the reason to write reactive pipelines.
What it is good at
The reasons teams pick it, stated concretely.
Backwards compatibility measured in decades
Code compiled in 2005 generally still runs. For organisations with software older than some of their staff, this is not a nice-to-have — it is why Java is there at all.
The JVM is exceptional engineering
Thirty years of JIT compilation, escape analysis and garbage-collector research produce a runtime that is genuinely fast and can be tuned for either throughput or sub-millisecond pause times.
Tooling that is decades ahead
IntelliJ IDEA and Eclipse offer refactoring, debugging and profiling that other ecosystems are still catching up to. Async-profiler, JFR and heap dump analysis make production problems tractable.
A deep, boring, reliable ecosystem
Spring, Hibernate, Kafka, Netty and the Apache stack are mature, documented, and used at scale by thousands of companies. Answers to your problem exist, and they are usually a decade old and still correct.
Virtual threads changed the concurrency story
Since Java 21 you can write simple blocking code and still serve hundreds of thousands of concurrent connections, without the cognitive cost of a reactive framework.
Trade-offs
Every language costs you something. Knowing what, before you commit, is the whole point.
Verbosity, though far less than its reputation
Java still asks for more ceremony than Kotlin or Python. Records, `var` and pattern matching have removed much of it, but the reputation was earned and lingers.
Slow startup and a large memory footprint
JVM warm-up costs hundreds of milliseconds and a baseline heap in the tens of megabytes. This is invisible for a long-running server and painful for CLI tools and scale-to-zero functions. GraalVM native images address it at the cost of build complexity and reflection constraints.
Framework-heavy conventions
A typical Spring application relies on annotations, classpath scanning and dependency injection that make behaviour hard to trace from source alone. Powerful once learned, opaque before then.
Version fragmentation
A large amount of production code is still on Java 8 or 11, so tutorials, Stack Overflow answers and libraries span a wide range of language capability. Check which version an example assumes.
Type erasure in generics
Generic types are erased at compile time, so you cannot write `new T[]` or check `instanceof List<String>`. It preserved compatibility in 2004 and has been an irritation ever since.
Code examples
Not syntax tours — the idioms that make code read like the language rather than a translation of another one.
public record Order(String id, String customer, BigDecimal total) {
// Compact constructor — validation without repeating the fields.
public Order {
if (total.signum() < 0) {
throw new IllegalArgumentException("total must not be negative");
}
}
public boolean isLarge() {
return total.compareTo(new BigDecimal("1000")) > 0;
}
}
var order = new Order("A-1", "Ada", new BigDecimal("1500"));
System.out.println(order); // Order[id=A-1, customer=Ada, total=1500]
System.out.println(order.isLarge()); // truerecord Employee(String name, String department, int salary) {}
Map<String, Integer> payrollByDepartment = employees.stream()
.filter(e -> e.salary() > 50_000)
.collect(Collectors.groupingBy(
Employee::department,
Collectors.summingInt(Employee::salary)
));
Optional<Employee> topEarner = employees.stream()
.max(Comparator.comparingInt(Employee::salary));
topEarner.ifPresent(e -> System.out.println(e.name()));sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}
static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> t.base() * t.height() / 2;
};
}try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
List<Future<String>> results = urls.stream()
.map(url -> executor.submit(() -> fetch(url))) // blocking call, cheap thread
.toList();
for (var future : results) {
System.out.println(future.get());
}
} // close() waits for every task to finishCommon pitfalls
The mistakes that cost everyone an afternoon at least once.
Comparing strings with `==`
`==` compares references. String literals are interned so it sometimes appears to work, then fails on a string built at runtime. Always use `.equals()`, or `Objects.equals()` when either side may be null.
Overriding `equals` without `hashCode`
Objects that are equal but hash differently silently disappear inside a `HashMap` or `HashSet`. Override both, or use a record and get both for free.
Mutating a collection while iterating it
Removing inside an enhanced `for` loop throws `ConcurrentModificationException`. Use `Iterator.remove()`, `removeIf()`, or build a new collection.
`float` and `double` for money
Binary floating point cannot represent 0.1 exactly, so currency arithmetic drifts. Use `BigDecimal` — and construct it from a string, not a double.
Returning `null` from a collection method
It forces every caller into a null check they will eventually forget. Return an empty collection, or `Optional` for a single value that may be absent.
Catching `Exception` and logging nothing
`catch (Exception e) {}` turns a diagnosable failure into a mystery. Catch what you can handle, log with the stack trace, and let the rest propagate.
In production
Where it is running at scale, and what it is doing there.
Amazon
Backend services, cloud computing, and large-scale distributed systems.
LinkedIn
Enterprise backend services and web applications.
Netflix
Microservices architecture and high-performance streaming services.
Uber
Backend services and real-time dispatch system.
Learning path
A realistic order to learn things in, with something to build at each step.
- 1
Weeks 1–2
Language core
Types and variables, control flow, methods, classes and objects, arrays, and the difference between primitives and references. Get comfortable reading a stack trace early — you will read thousands.
Build this: Write a console application that models a small domain, such as a library with books and borrowers.
- 2
Weeks 3–4
Object orientation and collections
Interfaces, inheritance, composition, generics, and the Collections Framework — `List`, `Map`, `Set` and when each is the right choice. Learn `equals`/`hashCode` properly; hash-based collections depend on them.
Build this: Replace your arrays with the right collection types and justify each choice.
- 3
Month 2
Modern Java and tooling
Lambdas, streams, `Optional`, records, `var`, the `java.time` API, plus Maven or Gradle, JUnit 5 and your IDE's debugger. This is the step that separates Java-8-era code from current code.
Build this: Add a Maven build and JUnit tests, and rewrite your loops as stream pipelines where it improves clarity.
- 4
Months 3–4
Building real services
Spring Boot for web APIs and dependency injection, JPA or jOOQ for the database, Jackson for JSON, and SLF4J for logging. Learn what dependency injection is solving before learning its annotations.
Build this: Build a REST API with a database behind it, integration-tested with Testcontainers.
- 5
Ongoing
The JVM itself
Concurrency and virtual threads, garbage-collector behaviour and tuning, profiling with JFR and async-profiler, and reading bytecode when a puzzle demands it. This knowledge is what makes a senior Java developer.
Build this: Load-test your API, profile it, and fix the bottleneck you find rather than the one you assumed.
Ecosystem and tooling
The tools you will end up installing whichever project you join.
| Tool | Category | What it does |
|---|---|---|
| Maven / Gradle | Build | Build, dependency resolution and packaging; Maven for convention, Gradle for flexibility |
| Spring Boot | Framework | The dominant application framework — web, security, data access and configuration in one |
| IntelliJ IDEA | Tooling | The reference IDE; its refactoring and debugging are a large part of Java's productivity story |
| JUnit 5 + Mockito | Testing | Standard unit testing and mocking |
| Testcontainers | Testing | Runs real databases and brokers in Docker for integration tests instead of fakes |
| OpenJDK builds | Runtime | Temurin, Corretto, Zulu and others — free, production-grade JDK distributions |
| GraalVM | Runtime | Ahead-of-time compilation to native binaries with millisecond startup and low memory use |
| JFR + async-profiler | Observability | Low-overhead production profiling for CPU, allocation and lock contention |
Java libraries
74 catalogued, each with installation, worked examples and best practices.
Spring Boot
The default way to build a Java service — auto-configuration over a vast, mature ecosystem.
Web & HTTPSpring Security
Spring Security is a powerful and highly customizable framework for authentication, authorization, and protection against common security threats in Java applications.
SecurityHibernate
The JPA implementation that defined ORM on the JVM.
Data & AnalyticsJackson
The JSON library the JVM ecosystem standardised on.
Web & HTTPGson
Gson is a Java library by Google for converting Java objects to JSON and vice versa. It supports serialization and deserialization of Java objects, including collections, generics, and nested objects.
Web & HTTPOkHttp
The HTTP client behind most JVM and Android networking, including Retrofit's.
Web & HTTP
Frequently asked
Is Java still worth learning in 2026?
Yes, if back-end, enterprise or Android work interests you. Java runs an enormous share of banking, insurance, retail and logistics systems, and those systems are not being rewritten. The job market is large, stable and well paid, and the modern language is far more pleasant than its reputation.
Which version should I use?
The most recent LTS — Java 21 or 25 — for anything new. If you are joining an existing codebase, expect Java 8, 11 or 17 and check before copying examples: records, `var` and pattern matching will not compile on older versions.
Java or Kotlin?
Kotlin is more concise, has null safety in the type system and is the default for Android. Java has a larger talent pool, simpler tooling and better backwards compatibility. They interoperate freely on the JVM, so the decision is rarely permanent and often team preference.
Do I need Spring?
Not to learn Java, and you should not start with it. For production web services it is the default in most organisations, and its ecosystem — Spring Security, Spring Data, Spring Cloud — is why. Quarkus and Micronaut are lighter alternatives with faster startup.
Is the JVM slow?
The opposite, for long-running processes: the JIT compiler optimises using real runtime behaviour, which an ahead-of-time compiler cannot observe. What is slow is *starting* — warm-up costs make it a poor fit for short-lived CLI tools unless you compile with GraalVM.
Do virtual threads replace reactive programming?
For most applications, yes. The main reason teams adopted reactive stacks was thread-per-request exhaustion under load, and virtual threads solve that while keeping code readable and stack traces meaningful. Reactive still wins where you genuinely need backpressure and stream composition.




