Java and AI (LLM) do not mix well

In my experience so far Python is by far the best language to use with an AI assistant. Java, on the other hand, is a hard nut to crack. Trying to use current crop of AIs on Java code leads to them blowing through the token budgets in no time, without delivering any value.

There is a reason to that, it is technical, but it stems from a very hard to measure inclinations of people writing Java vs Python code.

Let's start with the technical reason. Every time an LLM makes a tool-call it is a stop. The "TOOL_CALL" is literally one of the stop reasons. LLM stops its generation process, returns the desired call parameters to whatever AI-enabled application invoked it and goes away. Depending on the provider it may keep some of the context cached, but it may just as well throw it all out. Once the AI-enabled application completes the tool call it adds the results to the messages and calls LLM again. Each tool call results in a hard stop, caches evicted or go cold and so on.

The common tool in AI coding assistants is "read file". In a good assistant that'd specify line numbers as well to avoid dumping huge files into the context. But here is where the technical limitation is: it reads at most one file.

This works great with Python, as Python programs tends to have tightly packed files. LLM may need to read just a single file like book.py to change some behaviour of a Django application.

Not so in Java. In a typical Java application to change a behaviour of a single API you are likely need to read BookController, BookService, BookServiceImpl, BookFactory, BookRepository, BookRepositoryImpl, BookPermissionAdvisor, BookEntity, BookResource, BookServiceImplTest and the list goes on and on. Depending on how old is your codebase you might need to read a couple of XML files as well to know how all of those classes wire up together.

Each file is a reason for a separate tool call - a full stop in reasoning and a chance to evict the caches and get billed the full price of input tokens on all that data all over again.

While being technical, this reason boils down to the tendency of Java as a programming language to attract people who love layers of abstraction. Long gone are the times when Java only allowed a single Class per file, yet this is how most of the Java code is structured even today. And while steeped in old school OOP (I love SmallTalk), Java as a language was never dogmatic about those abstractions. And yet it just attracted the kind of people who takes pride in it. If a developer has an opinion on Composition-vs-Inheritance they'd feel right at home in Java. If they ever had any UML diagram printed and pinned to wall next to their desktop they would jump straight into any Java application.

Java is not the only language to attract developers with some quirk. Go developers love to re-invent a wheel. Perl developers take pride in smart one-liners. JavaScript developers tend to include a 3rd party dependency for everything.

All write software that works, but the particular quirk of Java developers tend to have makes it extremely expensive to use LLM Coding Agents.

I once tried Claude Opus 4.7 to implement a spec for a single API in a pretty typical Java application and that thing ate through the tokens at a breakneck speed without ever delivering much value. Its total per-hour price came to about 5x my hourly rate as a Java developer. And I can write a lot of code in an hour...

What's funny, is the good old "smart autocomplete" mode of using LLM is awesome with Java. Simply because there is so much boilerplate code to be generated. This one is cheap and fast and actually helps a lot.

Just do not try at home to do any of that fashionable "agentic spec-driven development" with Java codebase.

Posted On

Category:

Tags: /