Hey! Thanks for reading! Just a reminder that I wrote this some years ago, and may have much more complicated feelings about this topic than I did when I wrote it. Happy to elaborate, feel free to reach out to me! 😄
Statement: I am plenty happy to use Java in a large number of contexts.
BANG! BANG! BANG!
No, I'm not unqualified to say that. I'm not a defensive graduate from a so-called JavaSchool, I graduated from a pretty renown program. Like many engineers I often doubt my ability, but I've made it on the winning end of the Google Interview, and have written side projects in Erlang, Go, Racket, and Ruby. No company has ever fired me for technical ability or lack of contribution (one laid me off when they stopped making software); most have worked hard to keep me. It's very, very hard to evaluate engineering ability but for the most standard (often bullshit) metrics, I pass.
I acknowledge that even in the game Java is playing, C# often does it better. I've never had the opportunity to use C# given it's close association with Windows and the CLR; no firm I've worked with was using those, and when I choose technologies for my side projects, I usually use more obscure ones.
But frankly, I'll go further and say it's a damn good choice for many modules/projects.
Let's break it down…
Except for C++ in Visual Studio (real one, not the newcomer and again, kept away from many of us for being Windows-only), there's no other language I've worked in that has the level of amazing tooling that Java does. Eclipse is a plagued boat but I've always got it to do what I wanted to after enough wrangling (it's the IDE of choice at Google, who knows a thing or two about producing Java code). I prefer Intellij, but the fact that you have two semantically-aware, highly configurable IDEs with various plugins tells you there are two more options than virtually everyone else.
Remember that most of this is tied to what the language allows you to do: intentional or not, the same things that "limit programmer creativity" in Java (static type system, module system, JAR format) also enable it build effective tooling. Top class IDEs in other languages like DrRacket or RubyMine go as far as one reasonably can, but the dynamic nature of those languages makes it hard to automate many of the analysis tasks.
might be faster for me to port this whole codebase over to java and use the refactoring tools than to try to change this method name in ruby— Jake Boxer (@jakeboxer) October 20, 2014
I'm more than happy to admit ignorance here — there's likely a number of IDEs I don't know about that are an absolute joy to use, mind-bendingly powerful, and readily handle industry demands. But in the dozen or two languages I've written projects in, none except Java and VS have had an extraordinary story here.
This would be a punchline in the late 90's before dynamic languages swept the planet, but again, compare the landscapes here: for a GC-ed language with memory safety and a thriving library ecosystem, what beats it in performance? Ruby? Python?1 Node? PHP?!?!?2
The most popular implementations of these languages usually run in a single-threaded context. Most of them have worse garbage collectors than the JVM.
Scala and Clojure are great choices that share similar performance characteristics by virtue of being on the same virtual machine.
Let there be no ambiguity: I'm not saying Java has BLAST PROCESSING or anything. If you really want performance to shine in your program, Java isn't your choice.
But, if you're writing your program in Java over the alternatives listed above, you just won't have to worry about performance as often or as hard as the other memory-safe GC-ed languages listed above. Look at Jeff Atwood say that with the best hardware, Ruby performance is "good. Not great. Good."3 Programs written in most languages with comparable features to Java require nontrivial work to speed them up (or minimize their resource use) to match Java's performance characteristics. You could avoid that trek by just using Java.
(I've avoided mentioning Go and Rust because they are delightful, memory safe languages with decent concurrency stories, modern package managers, strong industry investment that perform quite beautifully. They can't catch up on the tooling or ecosystem soon enough!)
One of the nicest things about the languages I singled-out above is package
npm install --save make adding libraries to
your code easy and pleasant.
Luckily, you can get a similar system set up with Gradle and Maven Central. Like many parts of setting up your Java project, it's a major pain in the ass to get it running and you'll want to die a little. I mean, just scroll through the Gradle User Guide and be horrified by how much Stuff is in Yet Another Build Language. And wait till you run it for the first time, and get that signature JVM boot time!
But once you get over the initial hump, it's dead-easy to add code, just like with the languages above. And there are JARs for everything. Check out my post on Android libraries to get a sense of how much of a role it can play in your development, and Getting Things Done.
Sidenote: The JAR format, and there is so much shit is written in Java
I'll make another case here: JARs and Java's tooling are great too in odd cases where you might want to use an executable as a library. This isn't wholly unique to Java (lots of npm modules have a command-line mode and library mode), but the prevalence of many JAR-based tools make this a pretty solid plus. Here's an example that will probably be it's own post, but briefly:
I'm working on a web app in Erlang, and I need an asset pipeline that will minify + compress the JS and CSS. The libraries that look best (for my definition of best) for this look like the Closure Compiler for JS and the YUI Compressor for CSS. Both are command line tools distributed as JARs.4
The app does the minification itself (it watches its sources while running and recompiles/reloads as necessary, a la sync), but how can it call minification without starting a new OS process and heating up fresh JVM instance for each case? Well, the command-line programs are distributed as JARs, which means we can call its public interface from Java!
Long story short: I have a Jinterface node running a Java wrapper with both JARs as dependencies which, like most Erlang nodes, is always running and listening for messages. I just send an Erlang message to the node like any other, and the Java program calls the public interfaces in the JARs, as if they were distributed as libraries.
I do a similar thing with the owasp-html-sanitizer to make sure any Markdown submitted by users is safe to display on the site.
All this to say: a lot of code is distributed in JARs, and Java gives you an easy bridge to most of it, even if they were originally CLIs.
Unrelated: I love Erlang, but maybe it was a bad choice for the application logic.
In defense of idiot-proofing
Most smart devs I know understand that you don't want to be too clever, and The Zen of Python very nicely states that "Explicit is better than implicit. Simple is better than complex." We're all cool with this, and agree with it.
But holding a value dear is very different than actually honoring it, especially when it's a hard thing to recognize and do. Google, Apple, Facebook &c; will tell you day and night that they value diversity, but their numbers are dismal will likely continue to be, and nobody will be held accountable for it. Even if you know in your brain that you need to account for something, that doesn't mean you can or will.
In the talk What Killed Smalltalk Could Kill Ruby Too, Uncle Bob cites Ward Cunningham as having quipped that "what killed Smalltalk is that it was just too easy to make a mess."
I say all this to say, I've cleaned up some gross-ass messes in Node. I've produced some gross-ass messes in Racket, Erlang, and others. Truth is, if you've got a language that is expressive and gives you a lot of power, you can very well shoot yourself in the foot.
So many programmers who frequent places like HN or /r/programming swallow Silicon Valley kid-genius "10x" myths, cast themselves in those roles, and think that they're certainly beating the averages with the superior language choices and clever techniques. Other people make messes, but I'm using abstractions correctly!
Realtalk: have you ever met an Objectivist who believed the whole Ayn Rand philosophy while not also believing that they are one of Society's Great Creators And Thinkers? Ever meet one who espouses it enthusiastically followed by "and I'm one of the inferior moochers, destined to live off the works of the great ones?" Fucking never. Same thing happens with programmers and the "just right" level of abstraction: read any HN thread and observe a huge number of douchenozzles be convinced that they're some unicorn-blooded 10x hotshot, and the more humble of them merely believe they're fucking brilliant.
All this is a long way of saying — there are silver linings to having your hands tied in Java. You can certainly make messes in Java. But a) I feel like you really gotta work harder to make that mess with your hands tied, and b) with better tooling, I find it's often easier to navigate anyways.
A better, more thorough defense by example
Is available here. It's an excellent series in 3 parts that goes over a radically different workflow than most people expect when they think of programming Java. It's also a year old, so I expect a lot has changed!
It's perfect and I love it forever.
It's not and I definitely don't. But if someone says "I wrote it in Java/want to write it in Java" and you instinctively roll your eyes because it's not Bad Ass Rock Star Tech or "real hackers don't write Java," then grow up, kid. As with everything, there are tradeoffs galore, and I think you could do a lot, lot worse.
1: PyPy makes this tricky, but it too will fail in many cases.
2: HipHop makes this tricky too, for similar reasons. But ew, PHP!
3: At this point I've linked to the Holy Trinity of Tech Man blowhards: paulg, Jeff Atwood, and Joel Spolsky. I'm a Yegge short of hitting for the cycle. Please don't take this as an endorsement of their general views/influence, tef covers them pretty well in his talk, "programming is terrible: lessons learned from a life wasted."
4: Peanut Gallery will mention maybe throwing in a Grunt/Gulp script to uglify or something… I don't want to introduce another language into the build process; if you've ever worked with Erlang you know deployment is still very much in 1986. The developers behind rebar3 have expressed an interest in eliminating the need for external build commands like the old practice of a rebar.config + Makefiles, and I'd love to abide as long as I can.
Thanks for the read! Disagreed? Violent agreement!? Feel free to drop me a line at , or leave a comment below! I'd love to hear from you 😄