Every week, some developer crawls out of their legacy codebase to announce that Java is "too verbose." They'll tweet about it. They'll mention it in code reviews. They'll use it as an excuse for why their 200-line method exists.
But here's the thing: when I actually look at their code, it's not Java's fault. It's theirs.
The Real Problem? Your Fingers
Let me show you what I mean.
Here's the kind of code people write and then blame the language for:
User user = new User();
user.setName("Alice");
user.setAge(30);
user.setEmail("alice@example.com");
user.setActive(true);
repo.save(user)
Six lines to create one object.
Now here's the same thing written by someone who's actually read a release note since 2015:
var user = new User("Alice", 30, "alice@example.com", true);
repo.save(user)
Or hell, if you're not storing the reference:
repo.save(new User("Alice", 30, "alice@example.com", true));
One line. Done. You wrote six lines to accomplish what one could do – and you have the audacity to call the language verbose?
You Are The Boilerplate
Let's talk about the real sources of "verbosity" in Java codebases. Spoiler: it's you.
Still Writing Getters and Setters in 2025
If you're manually typing out getX() and setX() methods in 2025, you're not a professional developer — you're a
human code generator. Records have been around since Java 14. They're stable. They're production-ready. Use them:
public record User(String name, int age, String email, boolean active) {}
That's it. That's the entire class. You get constructors, getters, equals(), hashCode(), and toString() for free. But sure,
keep writing 50 lines of boilerplate and complaining about "verbosity."
Avoid var Because "It's confusing"
No mate, it's not confusing, but you know what is? this:
Map<String, List<ComplexBusinessObject>> groupedData = complexService.getGroupedData();
vs this:
var groupedData = complexService.getGroupedData();
This type is right there in the method name. If your method names are so bad that removing the explicit type declaration makes code "unreadable", your problem isn't var – it's your inability to write clear code.
Pattern Overload for Trivial Logic
We've all seen it: the UserFactory, the UserBuilder, the UserManager, the UserService, the UserHelper, the UserUtil.
5 classes to accomplish what should be a constructor and 2 methods.
Design patterns exist to solve actual problems, not to make your codebase look "enterprise". If you're creating a factory pattern to instantiate a POJO with 3 fields, you're not writing good Java – you're writing a resume.
Ignoring Modern Language Features
Java has evolved. Significantly. But some developers are still writing like it's 2005:
- Switch expressions (Java 14): Clean pattern matching instead of verbose if-else chains
- Text blocks (Java 15): Multiline strings without the nightmare of concatenation
- Pattern matching for instanceof (Java 16): No more casting after type checks
- Sealed classes (Java 17): Controlled inheritance hierarchies
- Record patterns (Java 21): Destructuring records directly in pattern matches
These aren't experimental features. They're here. They work. And they make Java significantly less verbose. But you'd know that if you'd read a changelog in the last 5 years.
Modern Java Actually Slaps
Let's be real: Java from version 14 onwards is a completely different beast than Java 8. Hell, it's a different species than Java 5.
Here's what you can do now:
// Records for data classes
public record Product(String name, double price) {}
// Pattern matching with switch expressions
String describe(Object obj) {
return switch (obj) {
case Integer i -> "Number: " + i;
case String s -> "String: " + s;
case Product(var name, var price) -> "Product: " + name + " with price $" + price;
case null, default -> "Unknown";
}
}
// Text blocks for readable multiline strings
var json = """
{
"name": "John",
"age": 30,
"city": "New York"
}
""";
// Streams and lambdas for functional-style operations
var adults = users.stream()
.filter(u -> u.age() >= 18)
.toList();
Is this verbose? No. Is it clear? Yes. Is it modern? Yes.
The language has grown up. Have you?
The Verbosity is Coming From Inside the House
Here's the uncomfortable truth: most "verbose Java" isn't a language problem — it's a skill problem.
You're verbose because:
- You learned Java once in 2010 and never updated your knowledge
- You cargo-cult patterns you saw in ancient Spring codebases
- You think "enterprise" means "uses as many classes as possible"
- You're genuinely unaware that Java has had major improvements in the last decade
- You're too lazy to refactor but not too lazy to complain
The language gave you tools. You just refuse to use them.
" But Python/JavaScript/Go Is Less Verbose! "
Oh, here we go again, the grass-is-greener crowd.
Yes, Python lets you write user = User("Alice", 30) without type annotations. Congratulations, you've discovered dynamic typing. Now wait until runtime to find out you passed a string where an integer should be, and enjoy debugging production.
JavaScript? Sure, it's concise:
const user = { name: "Alice", age: 30 }
It's also a chaotic hellscape where typeof null === "object" and everything is secretly a string. Hope you enjoy "2" + 2 === "22" and 3 different ways to declare variables depending on which year you learned the language.
Go is intentionally minimal, which is great until you need generics (oh wait, they just added those in 2022 after a decade of people copy-pasting code), or want a robust standard library for anything beyond network servers.
Every language makes tradeoffs. Java chose type safety, backwards compatibility, and explicit contracts. If that's "verbose" to you, you're really saying "I don't want to think about types" – which is fine! Just don't pretend it's a language flaw when it's design philosophy you disagree with.
The AbstractSingletonProxyFactoryBean Strawman
Let's address the elephant in the room: Spring Framework's infamous AbstractSingletonProxyFactoryBean.
Yes, it exists. Yes, it's ridiculous. No, you don't write that – Spring does. And you probably never interact with it directly.
Blaming Java for Spring's internal implementation details is like blaming English because legal documents are hard to read. The language isn't the problem; it's what certain frameworks built with it.
In fact, Modern Spring Boot applications are concise and straightforward to understand as hell, like, what average developer who's worked with REST frameworks wouldn't understand this???
@RestController
@RequestMapping("/users")
public class ApiController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
Optional<User> user = userRepository.findById(id);
return userRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found"));
}
}
Where's the verbosity?? Where are the XML files?? Where's the abstract factory singleton proxy whatever the hell that is?
Oh right, it's 2025, not 2008.
Your Null Checks Are Embarrassing And Shameful
Speaking of outdated practices, let's talk about this crime against humanity:
public String getUserEmail(User user) {
if (user != null) {
if (user.getEmail() != null) {
return user.getEmail();
}
}
return null;
}
Four lines, two null checks, one return value. This is what happens when developers learned defensive programming in 2002 and stopped learning.
Here's the modern approach:
public Optional<String> getUserEmail(User user) {
return Optional.ofNullable(user).map(User::getEmail);
}
Or if you're using records and keeping things null-safe by design, you don't even need Optional:
public String getUserEmail(User user) {
return user.email(); // Records can't be null by design
}
But sure, keep writing defensive null checks everywhere and then complaining that Java is "too safe" and therefore "verbose."
The Real Verbosity is Your Code Reviews
You wanna know what's truly verbose? That's right, your code reviews.
"This method is too long" – it's 8 lines, Karen.
"We should extract this into a separate class" – it's a single calculation used once.
"Let's make this more enterprise" – this is a startup, not Boeing.
The obsession with over-abstraction, over-engineering, and "clean code" taken to religious extremes has caused more verbosity than the Java language ever did.
Uncle Bob didn't say every method should be 3 lines, did he? He said code should be readable. Sometimes that's 3 lines. Sometimes that's 20. Learn the difference.
Conclusion: Learn or Leave
Java isn't verbose. Your mindset is.
How about doing us a favor by leaving to save us some time from re-reading your code if you refuse to grow your 2005 mindset.
If you're still writing Java like it's the era of XML config files and AbstractSingletonProxyFactoryBeans, that's on you. Modern Java is expressive, concise, and powerful – but only if you actually bother to write modern Java.
So either update your skills, or go back to your build.xml file where you belong. Some of us have one-liners to write.
Now if you'll excuse me, I have a 47-line "service layer" to refactor into 3 lines of actual logic
Top comments (13)
new User("Alice", 30, "alice@example.com", true);With this notation you significantly loose on code readability. What
trueactually does here?In other language it's solved with named params or object literals passed as params. Not sure what are the options for Java
I agree. but there are idiomatic ways to make this cleaner.
You can use the builder pattern:
it’s a bit verbose, but that’s the tradeoff: explicit over magical.
Every language picks a poison — Java just happens to prefer readability over shorthand.
That looks as best approach to me. Thanks for pointing this out
I mostly agree with the article, but still..
I think I found the verbosity in the example. It's in the
u -> uof the lambda.In Kotlin or Scala we have defaults for that and it's six to three times shorter (just
_orit).In Java we can optimize it to
.filter(User::isAdult), but then we get to the actual verbosity problem. Four new lines, including the one conventional empty line (thankfully not two as in Python) before or after the declaration:public boolean isAdult() {return age >= 18;
}
In C# that's a one-liner and you don't even need an empty line one before or after, without breaking any styling conventions:
public bool isAdult => this.Age > 18;As for Uncle Bob; he now found Clojure, which if well written, isn't even fair to compare in terms of verbosity.
(->> users (filter #(>= (:age %) 18)))Regarding your C# preferred-one-liner, how about that:
Predicate<User> isAdult = user -> user.getAge() > 18
One-liner (for those who appreciate it, as if it's the holy grail of coding), using common-known terminology (Predicate), I would also claim it's more concise: Who's this? Better be expressive: it's a 'user'.
(and yes, you can also spare the
getAgegetter, which no one actually writes (or has to read) nowadays: Predicate<User> isAdult = user -> user.age > 18 ; I personally prefer the getter.)Not sure who sees this line
(->> users (filter #(>= (:age %) 18)))and feels a lack of verbosity is something to appreciate... :)"Let's make this more enterprise" – this is a startup, not Boeing.
Literally lol'd!
These are good points, but a language is not just a language, it is an ecosystem.
I don't think most Java developers are start-up developers attempting to emulate enterprise. A lot of them are enterprise developers. You read a lot more Java than you write in these kinds of situations.
There's also a lot of conventions that can be dropped at this point, but have not been. Pick up any book on Java written in the last few years and it will still recommend writing getters and setters for all of your properties (they will mention records, but most of their examples will not use records). Many modern Java examples will also continue to avoid
var. When senior engineers who guide new engineers learning into the ecosystem and existing codebases continue to push for the use of old practices, it matters less that it is technically possible to write code in a cleaner and more modern way. Conventions take a long time to shake.Some additional information I need to add (so that I created an account):
That number 47 sounds like this is a post written, or at least assisted by A.I.
Records can be
nullUsing
Optionaleverywhere is an invitation to performance hit, may not be noticeable, but it might add up. I'd suggest usingOptionalonly for nested null check, and wait until JEP 401 is finalizedcase null, default -> "Unknown"can be just default -> "Unknown", default can handlenullcase.Other than that, this post is really, really cathartic. To the hell with the old bloated development mentality.
haha i really need to publicly address the " Records cannot be null " part because alot of people are confused by it. what i was trying to say is, if you design your data to be non-null by design ( validation, etc. ), then you don't even need the Optional.
and thanks for pointing out 3 & 4.
and no AI there, still human here. but ill take that as a compliment lol.
Great article!
Almost as if someone got into my head and spelled everything lies there out, to the extreme.. :)
I would claim an even more extreme statement: verbosity isn't always a bad thing, or something to avoid.
Sure, you can exaggerate with it and be too verbose, and that might harm your code, but being less and less verbose is also not a good place to be.
Eventually, most of the time, most of us usually read code (and not write it). Verbosity, to a certain extent, serves this purpose.
No one wants to read cryptic lines of code that only one person at the office might understand (regex people - I am talking to you!).
I teach students Java technology and ecosystem.
As an example, I show them this line:
class Student extends Person implements Comparable<Student>, HasNameIt's (almost) a valid English sentence, expressing the intent and meaning behind every word (Students extend a person; it aims to implement something called Comparable, etc.)
IMO, the alternative using common developer-characters (:) instead of pure, simple, meaningful English words (
extends,implements) is not something to be proud of, or push for.We gain nothing from this sentence
Student : Person, IComparable, IHasName, but even my mother can readStudent extends Person implements Comparable<Student>, HasName:)
Just use Kotlin. You still get the full benefits of the Java ecosystem and the JVM, but with a much better developer experience 🤷
Java is verbose compared to other languages (other than C & C++ at least)
Java is a high-level language.