
Why Java Sucks – Jonathan Gardner - TXV
http://tech.jonathangardner.net/wiki/Why_Java_Sucks
======
niftich
Such strong opinions.

 _> GC sucks_

 _> android app_

Android's runtime is not the Java Runtime. I'm starting to think Oracle should
have at least gotten some damages from Google for causing so many people to
think that the stuff _running_ on Android is _the_ Java and getting people
like this guy vocally misplacing the blame.

 _> name clash: X and Y have the same erasure_

Programmer unfamiliarity. Consume a List<T> with one function.

 _> Methods With the Same Name as Constructors_

Constructors are never void. Obviously, because they have to return the
object.

 _> Inner classes Don't Work_

This is a quip. What's the critique?

There are a handful of reasonable points but the overall product is not.
Furthermore, the pre-emptive rebuttals make it clear that there's no
convincing them.

~~~
flukus
> Android's runtime is not the Java Runtime. I'm starting to think Oracle
> should have at least gotten some damages from Google for causing so many
> people to think that the stuff running on Android is the Java and getting
> people like this guy vocally misplacing the blame.

Because java desktop apps had such a good reputation before android?

~~~
BoorishBears
No, but I said this the other day, Google made things worse by spreading its
"Java 6.5" hybrid mess. Now we have Java 6 with 7 features and Java 8 with no
Java 8 APIs being called Java 7 and Java 8 by people new to Java...

~~~
niftich
Indeed; looking back, we made the same points, and I don't think it's an
isolated sentiment. While Android may have positively affected the Java
ecosystem at first, official Java has long since evolved in appreciable ways
that Android-compatible code can't use. It's awful, and until Android gets a
wholesale port of the new APIs it won't get any better -- and despite Oracle
being no angel, none of this is their fault.

------
quantumhobbit
My main problem with Java is the people who use it. More specifically the
people who use it but have never used anything else and don't see anything
wrong with that.

Java is a great virtual machine, good open source libraries, an ok language,
and a terrible community of "best practices".

~~~
keefe
maybe you're measuring incidence rate without taking into account population
size? The fact that there are a lot more felons who patronize starbucks than
my local coffeeshop doesn't say anything about starbucks without another
datapoint.

------
balamaci
I lost it when the guy said don't use an IDE. What's the point of having a
static type system when I can't use an IDE to see where a specific method is
called.

~~~
jack9
When saying he works with a bunch of different languages and projects, but
then prefers Vim...It's great that Vim is better for older practiced vi
programmers (or opinionated middle aged), but the A/B testing is definitive
for new developers. IDEs are more efficient for most languages (especially
multi-language projects). Reducing the argument to "it shouldn't be this way"
is luddite.

~~~
gravypod
Not to mention the millions of features that I can't even begin to enumerate
that I use on a day-to-day that I wouldn't have the time in my life to master
without an integrated uniform method of interaction. Two of the best examples
are Eclipse's build system and hot code patching in debug mode.

The build system lets me forget entierly about "how am I going to write my
tup/make/cmake/anything file" as it just works when I click go.

The hotpatching debugger support is astounding. Nothing comes close to such a
seamless integration as being able to change my code and click "go" and have
my new method ready for action to see if it works on the next run.

You also get free autocompletion for everything. Oh god the ease of life
autocompletion gives you. I miss it every time I need to tough another
language.

~~~
crpatino
> The build system lets me forget entierly about "how am I going to write my
> tup/make/cmake/anything file" as it just works when I click go.

This is a bug, not a feature. Or rather, it is extremely easy for this to
result in subtle "works on my machine" scenarios.

1\. If you just "click & go", you are foresaking the ability to have automated
builds.

2\. If you implement the automated build independently from the IDE, you will
end up in a setting where the developer makes changes to the IDE settings that
are not reflected in the automated build. In a good day, this will result in
broken builds. On a bad day, you will have bugs that are imposible to
reproduce because the build QA uses is not the same as the build Development
uses, even if they both come from the same SVCS. On an ugly day, you ship to
your customers a binary version of the product that neither QA nor Development
have ever tested before.

3\. Not to mention that if you have no version control of the IDE settings,
every developer has a slightly different build of the project, one that mostly
works, until it does not. See the problems in #2 and extrapolate.

~~~
gravypod
> 1\. If you just "click & go", you are foresaking the ability to have
> automated builds.

This is incorrect. Eclipse will generate ANT files that are usable via
TeamCity.

> 2\. If you implement the automated build independently from the IDE, you
> will end up in a setting where the developer makes changes to the IDE
> settings that are not reflected in the automated build. In a good day, this
> will result in broken builds. On a bad day, you will have bugs that are
> imposible to reproduce because the build QA uses is not the same as the
> build Development uses, even if they both come from the same SVCS. On an
> ugly day, you ship to your customers a binary version of the product that
> neither QA nor Development have ever tested before.

Again, just keep your ANT file in your source tree and export it after every
change. This require far less maintenance then Make or cmake.

> 3\. Not to mention that if you have no version control of the IDE settings,
> every developer has a slightly different build of the project, one that
> mostly works, until it does not. See the problems in #2 and extrapolate.

The build settings are stored in the project files. When you download the
project and import it into Eclipse your build enviroment is kept in line.

In larger projects I use a CompanyLibraries project and inside it I have 1)
all libraries, sources, and documents neatly organized along with all binaries
involved with that library (so if it needs to import a .so or .dll it's there)
and the IDE-Bootstrap process:

    
    
       1. Go into your settings and import *.userlibraries
       2. Go to your settings and import cleanup.xml
       3. Go to your settings and import codetemplates.xml 
       4. Go to your settings and import format.xml 
    

You don't need to import the generated ant build system. You can right click
it and run the build & tests from there.

After you do this you have complete autocompletion for every library we use.
If needed you can cntrl-click to view source of a library, and it will work on
your system even if you have windows or linux (because of the way I setup my
.userlibraries). These are some from what I've seen the "little known" Eclipse
goodies for collaboration.

Could it be better? Yes I'd like to eventually write an eclipse plugin that
will automatically import these on a project by project basis then just make a
git submodule in each of my projects that includes the global configs to make
sure I still only have one.

------
khubo
A wise man once said. "There are only two kinds of languages: the ones people
complain about and the ones nobody uses." . I wish all the hate in the
universe is converted to something more useful ;) .

But.. Oh wait. public static void main? seriously?

------
DannyB2
If there were one perfect programming language, everyone would be using it
already.

If a particular language were horrible in every possible way, nobody would be
using it. If lots of people are using it, maybe you are not understanding why.

------
jgardner1
Hey guys, I'm the original author of that article, and I appreciate the
comments.

A few points:

* I started this article about 8 years ago.

* I've been trying to keep it up to date, so your comments are being reviewed.

* If you really, really love Java, I'm glad you found something in life to get passionate about.

* If you intend to be a professional software developer, you need to broaden your horizons before you start calling yourself senior anything. Java is only one programming language in the world.

Feel free to email me at jgardner@jonathangardner.net. I've been putting this
email up everywhere for a very long time so getting more exposure just helps
train the spam filters that much faster.

------
Randgalt
Which Java? Which JVM? Which libraries, etc.? JDK 8 bears little resemblance
to JDK 2. The latest JVM bears little resemblance to the first ones. Java is
old. It is a huge ecosystem with lots of warts and cruft. There is a lot of
good stuff, however, in that ecosystem and it's so good that it runs a huge
portion of the Internet. So, some good criticisms but too much missing the
forest for the trees.

~~~
exabrial
And, to add another point, Android is not Java either.

~~~
Randgalt
True - it shares some features, but different VM etc.

------
stevesun21
Nothing sucks at all aspects as same as nothing is great at all aspects. So, i
cannot see any useful information comes from this article at all. So sad this
person spends so much time to write a long article to hate a programming
language. :-/

------
AnimalMuppet
This reads a lot like the C++ FQA. That is, it looks like someone wants any
possible excuse to complain.

Now, in fairness, the C++ FQA has a lot more detail, a lot more specification
of reasons behind the ranting. I think the perspectives are both the same
(whiny ranting), but the C++ FQA is a large step above this.

------
gravypod
Are we using the same Java?

> GC Sucks So Badly, That You Should Avoid Using Memory

I'm assuming this is from before Java 8. The latest GC algorithms don't do
this.

> Worst of Exceptions and Value Checking

Sometimes the correct thing to do is to throw an exception and other times it
is to return a sensable value. An exception is an unrecoverable state, a null
is a sensable value for when nothing exists. Something not existing and an
unrecoverable state are two very different things.

> Won't cast an int to a long

Again, are we using the same language? This works. see code example at the
end.

> name clash: X and Y have the same erasure

This is not sensable behavior but entierly avoidable. Objects contain data and
then process them, then return the processed data to another object. The Java
way of doing this is to pass "List<Long> listOfLongs" and "List<String>
listOfStrings" to the constructor of foo and to have funcLong() and
funcString().

> incompatible types

I've never seen this but I also suspect that this isn't an issue as I've never
run into it and I've had interfaces in interfaces.

> static methods and members in a class

Static means the meaning of the method or object never changes. It will mean
the same thing in every instance of usage. As such this makes sense. You never
need to override a constant meaning as it will always mean the same thing.

> The "class" type is an afterthought

What does he mean by this?

> No control on member access

Use lombok. Not an issue and is fixed at compile time, not runtime.

> RSI

This makes no sense. An IDE is a tool that Java is deisgned to make use of.
Locking yourself in your cave and saying it's bad isn't going to pursuade
anyone.

> Camel Case

Nameing conventions aren't a reason a language is bad.

> Class-centric

That is the idea behind Java. The other concenrns not addressed by the title
have been fixed by the Java 8 additions allowing you to treat one-method
interfaces in Java 8.

> Iterators SUCK!

That is an implementation but it's fairly standard to just have tihs backed by
some form of collection and see if there is data left in it. I usually use an
index in an array and see if I have run past the end of the array.

> foreach doesn't take iterators

Yea this is crap.

> Function Pointers -- Missing

Java 8

> Constructors can't call each other

Again see the code at the end.

> Methods With the Same Name as Constructors

Yea that's allowed, I don't see what's wrong with that. It's a real function
name so it should be allowed. I've never accidently made this error.

> Run-time Dispatch: Fantasy

This is a design pattern issue but you're meant to use the highest or lowest
version of an abstraction. From there you can ideally handle it in a generic
way or if not you can use if (x instanceof Object) to filter out specific
cases.

> No Globals means Frameworks

This is where decorators and static/singleton classes come in handy. You can
do some amazing things with decorators, singleton/static classes, and if you
need it a bit of reflection.

> import is Useless

You can just use the fully-qualified name of the other class and it will work
fine. I've had maybe one instance where my naming conflicted with another
package but that was a rare case.

> No List Literals

Arrays.asList

> Inner classes Don't Work

I don't know what he means as this works perfectly fine for some design
patterns. Inherit state? No way. Provide impelemntations of an
abstract/interface for a specific object? Yes way.

In ArrayList it is perfectly fine to make an ArrayListIterator as they are the
same bits of ideas and as such should be in the same file.

I also prefer state enums to be defined in a class.

> Java is So Hard People Prefer to Write Code in XML, Jython, Scala, and
> Clojure

I don't do this only """ENTERPRISE""" Java developers do this. There's a lot
of great work being done moving away from this mentality but there is still a
lot to be done.

> Speaking of the JVM...

I'd love some numbers on these claims.

> DNS Client Implementation

Yea this is a problem. It's in here for compatability. There are many
libraries implementing this better at the moment.

> Sun Microsystems May Sue You

I don't know if this applies to OpenJDK.

> Why Use Java at All?

Why use any language at all? Write binary and opcodes (like I've been doing in
my CPU project). It's very fun!

In seriousness Java gets concurency right and I've not found another language
that lets me write concurrent code like this ever before. Very nice platform
to run on and one of the worlds best VMs. Everything is simple and documented
well. I don't need to read a novel to get something working. I can think of a
class, type that a control-space on my IDE, get a list of classes, find the
one in the right package and move on. No google, no searching, just tooling
and built in documentation. What's even better is most of the language is
implemented in Java! I have the sources downloaded so CNTRL+Click and I can
see everything's implementation! I'd love to see a python dev do that (I cant
and I've been writing python for years).

I'll be emailing the author at this email: jgardner @ XXX .net and giving him
this comment. I hope he can rebute some of these points.

    
    
       class Test {
       	private final int i;
       	public Test(int i) {
       		this.i = i;
       		this.test(i);
       	}
       	public Test() {
       		this(10);
       	}
       
       	private void test(long number) {}
       }

~~~
jgardner1
> > Function Pointers -- Missing

> Java 8

Yet again, they admitted an important feature was missing. Again, I am not
familiar with Java 8 but I suspect their implementation is horribly wrong.

> > Constructors can't call each other

> Again see the code at the end.

See my response.

> > Methods With the Same Name as Constructors

> Yea that's allowed, I don't see what's wrong with that. It's a real function
> name so it should be allowed. I've never accidently made this error.

I have. I guess I have just logged more time in Java than others.

> > Run-time Dispatch: Fantasy

> This is a design pattern issue but you're meant to use the highest or lowest
> version of an abstraction. From there you can ideally handle it in a generic
> way or if not you can use if (x instanceof Object) to filter out specific
> cases.

Please tell me how to do it properly. IE, if I have a variable of type Foo
that is holding a value of type Bar, how do I invoke the function with Bar
instead of Foo in the signature?

> > No Globals means Frameworks

> This is where decorators and static/singleton classes come in handy. You can
> do some amazing things with decorators, singleton/static classes, and if you
> need it a bit of reflection.

My point exactly.

Other languages just use globals. Because they are useful and people need
them.

Java makes you invent a new programming paradigm to overcome its artificial
limitations.

> > import is Useless

> You can just use the fully-qualified name of the other class and it will
> work fine. I've had maybe one instance where my naming conflicted with
> another package but that was a rare case.

And what do you do when you blow out the 80-char limit on columns?

Oh let me guess. You like your 1024-char limit on columns because you are
using a superior IDE.

> > No List Literals

> Arrays.asList

I don't recall that being an option. I do know that people used to prefer the
curly brace format but that turned out to cause memory leaks.

> > Inner classes Don't Work

> I don't know what he means as this works perfectly fine for some design
> patterns. Inherit state? No way. Provide impelemntations of an
> abstract/interface for a specific object? Yes way.

> In ArrayList it is perfectly fine to make an ArrayListIterator as they are
> the same bits of ideas and as such should be in the same file.

> I also prefer state enums to be defined in a class.

The issue with inner classes is that so many thing are contrary to
expectations. I started to list them all but it got too long. I'll have to
revisit it and try to condense it down.

> > Java is So Hard People Prefer to Write Code in XML, Jython, Scala, and
> Clojure

> I don't do this only """ENTERPRISE""" Java developers do this. There's a lot
> of great work being done moving away from this mentality but there is still
> a lot to be done.

The point is the reason why they do it is because it's easier to write, test
and debug these other languages than Java. People know that coding in native
Java is slow and cumbersome and time-consuming with no significant benefit.

> > Speaking of the JVM...

> I'd love some numbers on these claims.

What claims need numbers? LLVM and PyPy exist. JS with JIT kicks the pants off
of almost everything --- because it is compiled down to native machine code.
Go look them up for yourself.

JIT is the new fad, and it's a huge deal.

> > DNS Client Implementation

> Yea this is a problem. It's in here for compatability. There are many
> libraries implementing this better at the moment.

Name one.

> > Why Use Java at All?

> Why use any language at all? Write binary and opcodes (like I've been doing
> in my CPU project). It's very fun!

I write code to get the job done so I can get paid, my company's stock price
can go up, and I can get money. It's a job. Yes, I love programming, but I
prefer to get as much done with as little work as possible.

> In seriousness Java gets concurency right and I've not found another
> language that lets me write concurrent code like this ever before. Very nice
> platform to run on and one of the worlds best VMs. Everything is simple and
> documented well. I don't need to read a novel to get something working. I
> can think of a class, type that a control-space on my IDE, get a list of
> classes, find the one in the right package and move on. No google, no
> searching, just tooling and built in documentation. What's even better is
> most of the language is implemented in Java! I have the sources downloaded
> so CNTRL+Click and I can see everything's implementation! I'd love to see a
> python dev do that (I cant and I've been writing python for years).

Yeah, you strike me as someone who only knows Java. Let me know if I'm wrong.

> I'll be emailing the author at this email: jgardner @ XXX .net and giving
> him this comment. I hope he can rebute some of these points.

My email is jgardner@jonathangardner.net. It's been around for decades so feel
free to send me as much email as you like. I'll see the good stuff and the
spam folder will eat the rest.

Let me change your example:

    
    
       class Test {
       	private final int i;
       	public Test(int i) {
       		this.i = i;
       	}
       	public Test() {
                    this.test(7);
       		this(10);
       	}
       
       	private void test(long number) {}
       }
    

Tell me how that works out for you.

~~~
eip
>JS with JIT kicks the pants off of almost everything --- because it is
compiled down to native machine code. Go look them up for yourself.

>JIT is the new fad, and it's a huge deal.

 _The term "Just-in-time compilation" was borrowed from the manufacturing term
"Just in time" and popularized by Java, with James Gosling using the term from
1993.[16] Currently JITing is used by most implementations of the Java Virtual
Machine, as HotSpot builds on, and extensively uses, this research base._

[https://en.wikipedia.org/wiki/Just-in-
time_compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation)

Java definitely has room for improvement but claiming that JS is better or
faster is hilarious and makes me wonder what you are trying to sell.

JS seems fast if you only compare it to Python and PHP.

[https://benchmarksgame.alioth.debian.org/u64q/javascript.htm...](https://benchmarksgame.alioth.debian.org/u64q/javascript.html)

------
sanjamia
Argumentum ad Populum applies here. A carpenter extols the virtue and
efficiency of the nail and berates the screw and clip for its burdensome
application until his roof flies off in a hurricane.

------
jerven
Yes, java Sucks. But in many real and very important ways it sucks less than
any of the alternatives. Especially considering the age of the language, and
how backwards compatible it has been over the last 12 years.

Sure the eco system went all XML, but to be honest is the current JSON craze
so much better? Yet this XML heritage is not something one must suffer through
these days.

GC pauses, know your tools. Azul Vega was a thing in 2005 which means GC
pauses are an option not a requirement. Of course there is the whole family of
JavaRT as well and things like IBM metronome. If you have an big project
burning engineering hours on Java GC they should look further afield. Sure
most of these tools cost money. You think the extra hardware needed to run
most of this stuff in Perl is cheap?

Considering where python and perl went in their 5->6 and 2->3 migrations even
Java 1.4 to 1.5 was smooth. Heck even the annoying into of assert as a keyword
in 1.4 was painless compared to those. I know of 2 projects that even with
much more man power thrown at it have difficulty moving from Perl 5.8 to 5.12
and beyond. Gosh its like WebSphere migrations from 3 to 4 where unique in
that regards, not...

Look I understand, we all hate that crap java code some consultants and
solution experts wrote and that we need to deal with. But to be honest,
equivalent consultants and solution experts with Perl, C, Python or JS don't
create any better solutions. In someways Java pays the price of it being
practically so much better that these teams in their enterprise constrains
actually get something out of the door. Unlike, many other teams. Crap that
ships is much better than the stuff that never got anywhere.

The hasNext and next methods are very nice. Because the author assumes all
calls to next must be consumed. Well that is not true, and then having hasNext
return a boolean instead of an expensive object (e.g due to remote calls)
allows for lots of nice optimisations. Throwing exceptions for normal results
is a horror that is too common in Python, e.g. urllib2 and 302 redirects.

This actually is rant of someone who does not really seem to know better. Yes
there are some good points in it regarding generic erasure. And it is a pain,
but on the other hand it made the migration possible.

Hey if you don't like longs and int casting rules just use BigInteger
everywhere. Sure its slow, but so is the cpython and mri ruby implementations.
32bits is not the same as 64 and the Java Memory Model can be a rude awakening
if you use longs where you should have used ints.

The camelCase thing, use an better tool ctrl-alt-R and its done consistently
and correctly.

Things that would be nice too have in Java do exist. Getting Function etc.. in
Java8 would have been great a decade ago. Rust borrow checking would be nice
as well as a change in that locks operate (i.e. consuming a function that is
called on the data) instead of the otherway round (i.e. like Perl6 locks)

The advice to use Vanilla C as an option. A language where the equivalent of
following is undefined and can do anything? Including rm -rf!!! Sure no
implementation calls rm -rf on undefined behaviour, except every hacker coming
in via a memory corruption bug. A class of bugs that is not present in other
languages, and why it should not be your first port of call in the normal
circumstances.

    
    
      public class WhyIsThisUndefinedInC {
        int[] a = new int[]{Integer.MAX_VALUE};
        public test()
        {
           new Thread(()->(a[0]++).start();
           new Thread(()->(a[0]++).start();
           System.out.println(a);
        }
      }
    

In any well defined language you can have 3 outcomes, considering the total
lack of locking etc... C gives you infinite! Heck moving a small C code base
to a new compiler/libc combo is a massive undertaking in technical debt
reduction. Any of the other languages, except haskel lack a memory model that
is sane and useable (or any at all). When you can easily have 144 cores in
single box that is not a great place to be in!

Sure we all hate Oracle, and their Sales teams. But on the other hand most of
the time the customers deserve the sales team. Oh yeah I know its dirty to
actually make money on Software it needs to be sponsored by privacy invading
ad companies, or written by PostDocs with a lack of job stability. The JVM is
solid, and WORA is true for certified Java TCK passing implementations.
Android is not one of those.

