Why Java is Better than Python
Reason 1: Strong, static, compile time typing
I used to take Pythonistas at their word that they didn’t actually need strong, static compile time type checking. That was before I spent over a year writing Python more or less full time.
I am constantly blocked by not understanding which variables have which types. I am frequently spelunking through many levels of code and popping open the debugger to find out what type a variable actually has when. Not having explicit, enforced types makes code far harder to understand and edit.
Corollary: var
is very bad idea for Java and should not be used.
This is well known in the Python community today. PEP 484 is basically an admission that inline typing is a necessity for robust code, and Guido has admitted as much. It’s why large Python shops like Meta and Google have invested in tools like Pyre and Pytype to add strong typing to the language. These tools help, but they’re not as good as Java’s strong, reliable, static type declarations and type checking.
Reason 2: Checked exceptions
There are only two ways exceptions are handled in Python:
Method 1: Crash and dump the stack.
Method 2: Catch all exceptions, log an error message and a stack trace for each one, and then crash.
Yes, Python programmers could do better. No, in practice they don’t. I’m not talking about one-off hobbyist scripts either. Even major programs from big tech companies like Google fail badly here. When I was doing a lot of work in GCP, I routinely crashed the Cloud SDK, written in Python, leading to a stack trace that was not in my code and that I could do nothing about. When you’re contacting a network service, e.g. to deploy a new version of an App Engine app, it’s entirely possible the remote server will return an error. When it does, the Cloud SDK should look at the error code and report the problem to the end user in an intelligible fashion. Instead, more often than not, it prints a stack trace from the Cloud SDK’s own code, even though this is not the code that’s at fault. If any code was buggy, it was on the server but that stack trace wasn’t available.
This simply doesn’t happen nearly as often in Java, and checked exceptions are the main reason why it doesn’t. Java programmers have to go out of their way to ignore network failures. Python programmers have to go out of their way to handle network failures.
Even programmers who want to do better can’t because their dependencies don’t do better. Libraries can and do throw any exception and any time, and change which exceptions they throw when in patch releases. None of this is ever documented. Unless you control 100% of the code in your project, you can’t assume anything about which exceptions might be thrown when. Even if you think you control all the code, there’s nothing to prevent another programmer, or even your future self, from changing the exceptions in the code you depend on.
Reason 3: Performance
Python is slow. Sometimes this doesn’t matter. Sometimes it does. It matters more often than you think. For instance, even when I’m working on a program without strong performance requirements, Python routinely takes a minute or more to start up and run a unit test. That breaks my flow and prevents the fast feedback cycle Python was supposed to give us by being interpreted instead of compiled.
By contrast in Java, fast methods run fast. If a test isn’t doing very much, I can run it in less than a second in Eclipse or IntelliJ. Nothing in Python in VSCode is ever that fast. Maybe VSCode is the problem, I’m not sure, but I do know that I iterate code-test-debug way faster in Java than in Python.
Reason 4: Access Protection
Python doesn’t have private. Double underscores are a polite suggestion not to access something, not a rule. Python’s general philosophy on this is often summed up as “We are all adults here”.
Having now dealt with very large Python code bases written by top notch, very smart, highly paid Python programmers, I am prepared to say no, no we are not. I am very tired of being unable to change a dunder Python method in my own teams’ code because some alleged adult twelve time zones away made their mission critical product depend on the exact signature and behavior of our “private” method.
Tight dependency coupling is a bad traffic jam in Java. In Python it’s a Richter 9 earthquake that destroys all roads in a city and sets the gas stations on fire. The problems just aren’t at the same scale.
Reason 5: Javadoc
Python has doc comments but they’re rarely used or published. By contrast Java has a robust culture of documenting public APIs that enables Google to provide reliable answers for many questions. Outside the standard libraries, Python third party libraries rarely document methods adequately or make them available in a form Google can surface.