Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why Java Sucks – Jonathan Gardner (jonathangardner.net)
50 points by _tjxd on Dec 19, 2016 | hide | past | favorite | 53 comments


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.


> 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?


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...


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.


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".


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.


As a dyed-in-the-wool Java programmer, i have exactly the same observation about other language communities!

Except the Python lot. They seem pretty cool.


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.


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.


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.


As someone that bounced between Android development and webdev, who now does webdev full time, I can say the my biggest 2 complaints were always the build system and tooling surrounding the ecosystem. Luckily things have changed a lot in the web development world in the last two years. TypeScript and Visual Studio code deliver the autocomplete that I've wanted in web development for a long time and bring static typing to javascript, as well as handling the transpiling of new javascript features to older syntax all directly in the editor.

Webpack's hot module reloading is also incredibly useful if you take the time to set it up. You don't even need to hit 'go'. When you save a file, it incrementally compiles that module, and swaps it out on the client. This process is normally faster than me tabbing over the other window, and if you have you're project set up correctly, preserves the app state if it can.


I also love IDEs. Java without IDE - forget it.

But let me point you to the classic article by Steve Yeggie who inspired my commitment to emacs.

https://sites.google.com/site/steveyegge2/effective-emacs


> 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.


> 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.


I'm not a luddite.

I just prefer the best tools for the job, tools that can be used with any software project. The Unix IDE is the best in the world.


His point as far as I can tell is that Java is somewhat verbose and you really should you an IDE. There are languages where going without IDE is feasible. The need for an IDE is a sign of cognitive and wrist tax Java imposes.


To catch type errors well ahead of run time.


What's the point of a static type system if I'm going to write unit tests anyways?


When I'm working in a dynamic language I write many, many, many more tests than when I'm in a language with static typing.


A static type system makes code self documenting, easier to refactor and more maintainable


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?


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.


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.


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.


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


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


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. :-/


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.


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) {}
   }


You can't just dismiss concerns with "fixed in Java 8."

First off, not everyone is on 8 or can upgrade even if they want to.

Secondly, version 8 is, well, version 8. That's _20 years_ before the issue was addressed! 20 years of library code written to work around it and of cognitive models to work around it. You can't just wish that away, and it's perfectly valid criticism.


If a issue has been fixed it makes little sense to continue to complain about it.


Like I said, just because it's "fixed" in the core doesn't mean there aren't still implications being worked out everywhere else. It's not that black and white.


"Fixed in Java 8" means "You were right but that has been addressed".

I agree with the author in this case and it should be obvious that I do. It's a completely sensable point. I'm not arguing for Java X version I don't like. I'm arguing for Java as an evolving standard. No one in their right mind would think that many of the other languages the author loves are perfect in older stages.

Python 2? Who the hell represents strings as byte arrays? This was a mistake back in the Bell Labs day. It's the "vintage" of computer science.

Does that mean python "sucks"? No, quite the contrary. It means python is good because it will evolve with the times and fix it's issues as it runs into them.


I tend to agree with your points here - if you end up in a conversation with that guy, I would also add:

1 Java does get concurrency right and the trade-off made in going to a single threaded nodejs process will appear (as I have bitterly learned) as performance becomes important. Keeping a sanitary event loop (think about large uploads, downloads) turns out to also be a difficult problem and one with less tooling and experience.

2. Allocate Direct can be used to get off heap memory, I don't recommend doing this, but if you really need to worry about your GC pauses, then it is very possible to use java without it and I have seen that done.


> 1 Java does get concurrency right

Strangling yourself with mutexes on shared memory is not "concurrency done right".


no that's concurrency done right, used wrong. What do you want, immutable structures or event loop?


Parallelism using message passing. Writing with shared memory is so easy to mess up. Been in both worlds, one is sensible, the other is atrocious.


I think you've highlighted the answer there - that working with shared memory is easy to mess up and that immutability and message passing both provide some attractive aspects. The thing is, not every problem is solvable (and to a much larger extent, optimizable) without some concept of concurrency and all of the problems of mutual access that come along with it. I don't think the mutual exclusion problem is typically that bad with modern java - profilers let you visualize your locking issues, atomic variables let you squeeze cycles and really the correctness problem is not that hard, it's the performance optimization problem. I would rather my problems be explicit and in front of my face than hidden in some detail about event loops, method invocation time impacting other method invocations and so forth. The other important point is that as soon as you get into working in a clustered environment, you start having to think about distributed locks and concurrency when there is not even a shared clock to rationalize things. So, for product oriented engineers, great go use nodejs and you can write JS on the front end and the back end and it will be absolutely tremendous guys, I am telling you :) If we want to talk about judging languages on technical features (as this article starts the ball rolling on) then we can't just bandaid real problems with easily approachable solutions and write off any actual complexity as out of scope.


> I don't think the mutual exclusion problem is typically that bad with modern java - profilers let you visualize your locking issues, atomic variables let you squeeze cycles and really the correctness problem is not that hard, it's the performance optimization problem.

This only allows you to strangle yourself in a more CPU-efficient manner.

Locks et al. are low level interface, too low level for a language that pretends to be a high level one (like Java does).

> The other important point is that as soon as you get into working in a clustered environment, you start having to think about distributed locks and concurrency when there is not even a shared clock to rationalize things.

Once you go into clusters, you loose your precious notion of shared memory anyway (unless the distributed shared memory is still a thing; I haven't checked lately, but I thought it was an abandoned paradigm).

> So, for product oriented engineers, great go use nodejs and you can write JS on the front end and the back end and it will be absolutely tremendous

I don't know why are you implying that I either work on frontend, with web applications, or Node.js. I do none of these.


>This only allows you to strangle yourself in a more CPU-efficient manner.

I thought you meant losing cycles due to blocking or spinlocks when you said strangling.

>Locks et al. are low level interface

Actually no, this is the world of multiple cores. Threads are the most trivially accessible way to parallelize activities, so they are just a modern primitive.

>Once you go into clusters, you loose your precious notion of shared memory anyway

Zookeeper. Distributed clocks and sequences and all that often require a few bits.

I was just making fun in the last sentence, if you didn't catch the linguistic joke about populism in my word choice. I'd guess you work in erlang.


> Parallelism using message passing.

So... both immutable data structure (messages) and an event loop (message queue/reader).


You should (all Java devs) take a shot at being a gopher.


A Java developer is the last person I'd recommend gopher to. Having experienced the benifits of interfaces and abstract classes used to create Generic Methods I'll never go back.

C and Python developers are your best bet.


Hi, this is the original author. You sent me an email asking me to respond so I will.

> Are we using the same Java?

No, I originally wrote the article back in 2008 or so.

>> 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.

AFAIK people still complain about the GC. I've noticed that more modern languages don't have advanced GC like Java's.

>> 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.

I rarely deal in absolutes when I'm coding. It's all about engineering tradeoffs.

It's true that something not existing may not be an error, but often it is, particularly when you expect it to exist. IE, if I go to fetch a record by ID from the database, but it's not there, there's no way to recover from that type of error.

An exception does not represent an unrecoverable state. It just represents that your code doesn't know the proper behavior. For instance, in a web server, the proper behavior is to throw a 500 and log the exception causing the error. In a UI, you might want to show a dialog box explaining the error and its source, maybe even sending the stacktrace to the developers. A CLI will print the exception and cease operation.

Mid-level code doesn't necessarily know what the appropriate response to an error is, so it shouldn't have to have to check for them. If things are working as expected, no exception. If something goes awry, let the calling code figure out the right response.

>> Won't cast an int to a long

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

Did you read my update?

> > 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().

So, you have to encode in the name of the function the type of parameters it takes?

And what's the point of classes if you can't take advantage of them?

> > 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.

It is an issue. LinkedList is a type of List, so a List<LinkedList> should match a List<List>. It certainly knows that a LinkedList<List> matches List<List>.

> > 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.

You seem to use this argument a lot: "You never need to..."

Did you read my introduction to the topic?

> > The "class" type is an afterthought

> What does he mean by this?

Originally, classes in languages like C++ were simply syntactic sugar. You could not have a variable that stored a class. It didn't make any sense, anymore than a variable that stored a function.

Java continues this tradition.

In every other language, classes are first-class values that can be stored by any variable. So are functions.

The idea of storing a class in a variable is probably just as foreign as storing a variable in a function to a Java coder.

> > No control on member access

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

Or I could use Python.

> > 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.

Let me help you understand.

A programming language like Java consists of many parts, but in the end, it is a program that takes a bunch of text files and converts it into bytecode that the CPU can understand and execute.

Why do you insist on using an inferior programming language that requires the use of specialized tools, when those tools can be built directly into the programming language itself? IE, if I want to create a class, I'll just type "class A", not load up an IDE, click around a few times and hope I fill in the boxes right to have a hundred lines of boiler-plate code autogenerated for me.

It's not the 1960s anymore. We can write code that writes code. Let's do more of that and less fussing with the minor details that no one cares about.

> > Camel Case

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

It is if you have to type those names.

> > 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.

I'm not familiar with Java 8, but it sounds like they realized how bad of an idea it was if they're moving away from it.

> > 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.

So you're saying I shouldn't use iterators because it's easier just to code around them?

Iterators can be a powerful programming paradigm that is a major head-ache saver and time saver, but Java's implementation is so horrible you're recommending avoiding it. Got it.

> > foreach doesn't take iterators

> Yea this is crap.

I bow to your superior arguing skills.

continued ...


> AFAIK people still complain about the GC. I've noticed that more modern languages don't have advanced GC like Java's.

I don't know many people who complain about Java 8.

> Mid-level code doesn't necessarily know what the appropriate response to an error is, so it shouldn't have to have to check for them. If things are working as expected, no exception. If something goes awry, let the calling code figure out the right response.

That said Null is still a valid responce. Sometimes it gets out of hand from implementation buy specifically .INI file readers I'd expect to return Null or Default if available for an unset property. There are many cases for null but that doesn't mean that it isn't abused.

> So, you have to encode in the name of the function the type of parameters it takes? And what's the point of classes if you can't take advantage of them?

I think your usecase there is indicative of a lack of understnading about the abstraction that classes present. Onesuch representation would be to not expose internal datasets. Another is to, if you need to exept a generic dataset make your function generic.

> Let me help you understand. A programming language like Java consists of many parts, but in the end, it is a program that takes a bunch of text files and converts it into bytecode that the CPU can understand and execute. Why do you insist on using an inferior programming language that requires the use of specialized tools, when those tools can be built directly into the programming language itself? IE, if I want to create a class, I'll just type "class A", not load up an IDE, click around a few times and hope I fill in the boxes right to have a hundred lines of boiler-plate code autogenerated for me. It's not the 1960s anymore. We can write code that writes code. Let's do more of that and less fussing with the minor details that no one cares about.

To quote you: you sound like someone who only uses vim. There is much more to an IDE then clicking New File. Again I do most of my prototyping outside of IDEs and move it into IDEs for the features that it provides.

VCS, static analysis, type checking, refactoring, debugging. All of this at your finger tips.

> It is if you have to type those names.

These are bad naming standards: __init__, __name__, __eq__

Magic names are not the answer. Names are only a problem if they are the only source of meaning.

Java's naming is a convention to help you be a better programmer but you don't need to use it. In python, some naming is forced on the programmer with no say inherintly in the language. The language will not work if you don't use their naming. This is not the case in Java.

> I'm not familiar with Java 8, but it sounds like they realized how bad of an idea it was if they're moving away from it.

If they are moving away from it then does it still "suck"?

> So you're saying I shouldn't use iterators because it's easier just to code around them? Iterators can be a powerful programming paradigm that is a major head-ache saver and time saver, but Java's implementation is so horrible you're recommending avoiding it. Got it.

I'm commenting on your iterator implementation. It's incorrect and not the best way to do it. The iterator is an abstraction and using a 1-item-stack is not an idea implementation. Compounding other datastructures to implement your data structure is the less-harmful alternative.

> I bow to your superior arguing skills.

I see no point in arguing against something that is correct. I also don't see how one flaw can make something suck. If you feel that way you should re-evaluate your love for JavaScript.


> That said Null is still a valid response. [...] I'd expect to return Null or Default if available for an unset property. There are many cases for null but that doesn't mean that it isn't abused.

We use a `Maybe<X>` return type that can handle returning a value (including `null`), an absence of value, or an exception. It extends `Optional<X>` and adds a new `isPresent()` method, and wraps the exception in such a way that the result `isAbsent()` and calling `get()` will rethrow the exception. Very useful...


Null is meant to be used when it is likely there is a default handling for the responce. For instance

   String favoriteColor = accounts.get(username);
   if (favoriteColor == null) favoriteColor = "blue";
   setWindowColorTo(favoriteColor);

Removing null does not make your code more safe. Wrapping Null in more code does not make your code more safe.

You get null for free. I could write the same think that optionals do in Java with 1 static method

    public static boolean isAbsent(Object o) { return o == null; }

    public static <T> T get(T o) {
        if (isAbsent(o)) throw new RuntimeException();
        return o;
    } 

Now you get your nice abstraction from an inlined function. Wrapping it in an object in my opinion is bloat around seomthing that doesn't need it.

The best chance your have to sell all Java devs on something is @Nullable which is a fantastic idea. It lets you know where null WILL propegate so you know where to control it. IT will also help you get out of "I see NullPointerException so therefor null is the problem, not my code!"


> > 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.


>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

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...


Works just fine if you change:

    this.test(7);
    test(10);
to

    test(10);
    this.test(7);
Of course, since this is a made-up example to highlight one of your pet problems I don't know if that ordering is important to you. However there is a reason for the insistence on calls to the constructor being first, and it's not specific to Java. You run into this problem any time you have code that might mutate a data structure before if has been initialized. There are other ways to write this kind of code that avoids this, but it is by no means unusual in imperative code.


> 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.

Admitting something is broken does not mean it sucks. See this comment: https://news.ycombinator.com/item?id=13216187

Also, please read this before you wave it off: http://stackoverflow.com/a/1073427

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

Java is probably my most used language and that's saying something as I work as a TA for a Python class, use python for most personal projects, and also use many other languages. Java consumes the most time because it has the most polished toolings and standards for developers. Now they may not always be ovserved but if you stay in your own walled garden everything is all honky-dory.

You will never make these mistakes if you follow basic practices in Java's naming conventions. All lower case classpaths, all uppercase class names, lower then cammel function names, etc. You'll never be able to mistake Test() for Test.test() as they are instinctivly different names.

> 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?

    void something(Foo f) {
        if (f instanceof Bar) {
            (Bar-Specific commands)
        }
        (generic commands)
    }
Or better yet use your magic want: Abstraction. Wave it around and use your super powers to move that functionality into Foo and in anything that needs a specific handling of that function, override that.

> 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.

Well if you want to resort to global constants you can. Use a static import. LWJGL makes heavy use of this anthough I dislike it. I'd rather have an abstract interface into the library rather then have a global constant.

> 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.

Yes very much so. Please see this: https://www.youtube.com/watch?v=wf-BqAjZb8M

Line length != good code. Now granted, that doesn't mean run wild but I do have some code written that is perfectly good code, I've just ended up using some long variable names. This happens in Python as well. And no, you don't need an IDE for this, I write most of my prototype Python in nano before moving it into an IDE as Python IDEs are extremely sub-par.

> 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.

I don't remember `new int[] {};` causing memory leaks but yes you can even do a static import to do the following: `asList(1, 2, 3, 4)`.

> 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.

I'd love to hear it, and I'd love to define a set of "sane" sub-features of sub-classing in Java. I've working with libraries that where HORRIBLY written that have used sub-classes and I've also worked with amazing ones.

> 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.

I don't think this is the case. Enterprise Java came about because design patterns, like viruses, spread through code bases. You should look at this: https://www.youtube.com/watch?v=JxAXlJEmNMg

David goes through the history of development and I find it enlightening. He mentions it VERY breifly but many government contractors and researchers ended up using XML a lot. It came from another standard that they developed. As such, it was easier for them to write XML templating.

Then again this isn't a bad thing for two reasons:

    1. Someone else being bad at writing Java doesn't mean Java is bad.
    2. Sometimes XML is the correct way to do things. Do you write ALL of your web pages in Javascript adding elements in with document.createNode....()? No you use an XML notation. 
Java has gotten out of hand with XML because monkey-see-money-do but that doesn't mean the language is bad. I blanket refuse to use XML-requiring libraries. I just right my own implementation if it's required. I've done it for a game I'm working on. I've tossed all UI libraries as they all need XML and I think it's a waste of my time. I can write the library, and then use the library faster then I can read all the documentation about writing their stupid XML format.

> 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.

I've worked a lot with NodeJS, I've worked a lot with LLVM, and I'm about to do a lot of work with libdill (you'd like it if you've not seen it). I love lazy evaluated, JITed, and optimized languages. Runtime or no. That's why I love Java.

Java, especially after Jigsaw, will have major opprotunities to blow other languages out of the water. Java is great in runtime performance but horrible in startup performance. For server applications you can't get much better.

> Name one.

http://www.dnsjava.org/

I think Commons has one but I like this better as it's not-Commons. In my book that's a feature.

> 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. > Yeah, you strike me as someone who only knows Java. Let me know if I'm wrong.

My resume includes Python, JavaScript, C++ (now), C, Java, PHP, X86/ARM Assembly, LISP-Like languages and a few other things that I'm not remembering off the top of my head. I've got one project coming up in Go as well. This is in order of most-recent-project. Today I wrote something that will search craigslist and ebay for a x220t with an I7 and email me all of the results under $200. I'm looking for one and I'm in college so I'll just wait it out for the price to be right. Anyway, that was a Python project.

I also TA for a Python class at my university which I've successfully shot down trick questions from that one way-too-smart student that we all were once a time (He tried to tell the prof to use xrange instead of range for a performance boost and I had to bud in and say "xrange was removed" since he was stuck in the land of Python 2). I've also ported over Python code bases from 2 to 3. I mention Python so much because it seems as if you're a fan.

I hope that well establishes my programmer-cred.

>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) {}
   }
This is the best behavior to have. If you haven't initialized the state of a class you shouldn't acess it's methods. I'd rather have this rather then have an uncertianty about the contents of uninitialized state.


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.


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: