Hacker News new | past | comments | ask | show | jobs | submit login
JDK 8 Release Notes (oracle.com)
320 points by vkhuc on March 18, 2014 | hide | past | favorite | 310 comments

You know, I've been messing around with Java little lately. Nothing too fancy. It's actually not a bad language -- with a modern IDE it's actually pretty quick and breezy to work with.

If the standard library was cleaned up and the warts were all removed and filled in, even if it broke compatibility (call it Java X or the Latte language or something) I'd be okay with that. There's too much old 90's cruft hanging around making usage of different pieces non-standard and lots of over-objectizing everything so you end up having to assemble lots of things out of little pieces, boilerplate-like, that should just be a single import and instantiation.

The modern JVM is surprisingly quick and robust technology and I've been pretty happy with it in my limited tests. I ported some old Perl algorithms to it and got some really good speed out of it once I benchmarked some of the collections a little.

Some things should just be outright fixed, like a proper regex literal so I don\\'t have to \\e\\s\\ca\\\p\\\\e everything so much\\\\\//\/\\.

It's "got good bones" and a refurb of the entire thing to bring it focus could breath a lot of long-term life into it.


I guess what I'm trying to say is it would be great if the language was informed a bit more with what's going on in the dynamic languages space like Go has been. I like how Python is about as clear as Java code is, but it's always seemed a little more quick and breezy to work with. This is something I think Go got right and it'd be great if Java sort of caught onto this.

A major cleanup of the Java libraries is scheduled for Java 9. The JVM actually does not surprise anyone who's been working with it for a while: it is downright the most performant, flexible and awesome runtime environment ever developed. I've been playing around with lots of languages and environments in my pretty long career and, in the past decade, have always come back to Java (or the JVM). It feels like driving a Ferrari where everything else is at best a Toyota - might be easier to handle at first, but it's not your dream car.

This pattern, by the way, has been going on in lots of tech companies. They always end up going back to the JVM.

Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use), cool and extremely useful capabilities like dynamic linking and bytecode instrumentation, and unparalleled monitoring and profiling tools. It's the most professional platform you can choose (unless you're limited to Windows, in which case .Net is also an option). It's so far ahead than anything else out there, that the competition can only beat it in very specific use cases (e.g. Go is much better at startup time as well as standalone packaging, and C has better performance, though mostly in single-threaded programs). But nothing else gives you the whole package of performance, flexibility, maturity and monitoring.

> Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use)

It's getting easier



I think clojure is also actor based.

In my opinion http://www.typesafe.com stack is the most powerful and consistent one running on JVM. Scala/Play/Akka/Slick/SBT speaks for itself and I enjoy every day of working with it.

Not sure if I enjoy SBT but Scala/Play/Akka is definitely great

Does anyone enjoy SBT? My love for Scala is profound, but fuck SBT

Yes, I enjoy SBT. I miss it every time I end up working with similar tools for other platforms.

I'm not crazy about the syntax and I avoid build.sbt files, but as a tool it's very pragmatic and takes care of my needs perfectly. It has incremental compilation and continous testing built in. For testing within SBT with something like say ScalaCheck simply works out of the box with no configuration necessary, by simply slapping a ScalaCheck test in the test directory. SBT has cross compilation support, something that is needed for Scala. Some of the best Maven plugins have been ported to it (I enjoy sbt-release for example). I tried my hand at writing a simple SBT plugin and it really isn't bad. Dependency management is based on Maven repositories, again something that I miss a lot on other platforms. Publishing stuff on Sonatype has been painless. SBT's support for sub-projects in the same repository worked flawlessly for me and it is easy to setup. The console support is great too, allowing one to easily open a Scala console with the right classpath loaded (compile/runtime versus test). And in general I like how it just works out of the box.

Every time I end up interacting with Python for example, I get headaches from the clusterfuck that is setuptools, easy_install, pip, wheels, virtualenv, virtualenvwrapper or whatever the fuck they are using these days. Every time I interact with Ruby, I get headaches from rake, gem and gemspecs, bundler, rbenv, rvm or whatever else they are doing these days. I don't even want to remember Javascript and the clusterfuck that is npm, bowler, brunch.io, grunt.js, closure, amd, commonjs, browserify or whatever else they are doing these days. Or about .NET that's still in the Ant/Delphi age with MSBuild.

For Scala, the only fair competition that SBT has is Maven. And the only (other) pragmatic build/packaging/dependency management tool that I used has been Clojure's Lein, but lein lacks for example the capability of keeping a JVM process loaded, so you suffer the startup time every time you invoke a command, plus it seemed weird that lein doesn't offer things like continous testing out of the box. And speaking of configuration formats, lein's profiles are simply confusing.

You don't have to use SBT if you don't like it. Maven works fine and SBT's secret sauce, which was the incremental compilation, has been extracted in project Zinc and so it now works with Maven. But I still prefer SBT over Maven and when switching to other platforms it now feels like going back to 1999.

Minor correction: SBT's dependency management is based on Ivy's not Maven's.

And for those working in Scala and building with Maven still, I second the recommendation to download & run Ivy, turn on the useZincCompiler option in maven-scala-plugin's configuration, and enjoy substantially faster build times (and automatically falling back to a normal build if Zinc isn't running). You don't even need to specify a scala home directory for Zinc like it claims; scala-maven-plugin will tell Zinc to use the Scala libs from your Maven repo.

You're right, I meant something else - publishing artifacts happens on Maven repositories, using a Maven POM file as descriptor (or indeed an Ivy file, but libraries are usually published Maven-style).

I like this a lot. Setting up your own Maven repository on your own server, that can be internal or whatever, can be as simple as setting up a server that serves static files and the publishing itself is just copying files by means of SFTP or whatever. The protocol for finding all the listed dependencies on that server is also simple, so in case of problems you can usually understand what's going on.

This is much saner than the alternatives I've encountered on other platforms.

This. One can dislike the syntax but SBT's advantage compared to most other tools is IT WORKS.

SBT, also known as Slow Build Tool in my office.

Once I got my head around it, I began liking it. If you're using Akka's clustering, SBT's multi-JVM testing is killer.

I hate it and minimize its use while using other build tools whenever I can (in the same project).

Clojure is not actor based but has some terrific primitives for concurrency

Quasar's Clojure API[1] gives you very Erlang-like Clojure actors.

[1]: https://github.com/puniverse/pulsar

Specifically, core.async brings Go-like goroutines (channels) to Clojure.

On the off chance that readers aren't aware, pron, the GP, is the author of Quasar.

The JVM has a couple of pretty significant problems when trying to work with functional-style languages. The biggest one is the way it deals with the stack: It's not in the heap, and it's pretty limited, so with something like scala, and more specifically with scalaz, you have to do some contortions to avoid overflows. 90% of usages of scalaz trampolines are nothing but ways to work around JVM limitations.

I'd argue that today, you are better off with the .NET VM, as far as features are concerned. But being stuck in windowsland is really a non-starter for all kinds of applications. I can send a major task that will take 400 computers for a week to Amazon if my code relies on the JVM. If I write it in .NET, not so much

The stack doesn't have to be in the heap to make things better for recursion* , the JVM just needs to support tail-call optimisation.

See my blog post: http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and...

I'm excited to see tail-call optimisation ("proper tail calls") coming to JavaScript. Hopefully a bit of competition will encourage the JVM to clean up its act too.


(* Heap-allocated frames can help with other things though, e.g continuations.)

In Scala I work with self tail recursive functions all the time. Scala optimizes self tail recursive functions just fine, rewriting them as simple loops.

Yes you do have to use trampolines for mutual tail recursive function, because the JVM currently lacks support for it, however if you take a look at the Da Vinci sub-projects in OpenJDK, a prototype has been in the works for quite some time, led by none other than John Rose and given the attention that invokeDynamic is getting, I have no doubt that this will also happen on the JVM: http://openjdk.java.net/projects/mlvm/subprojects.html

Also, Scalaz great as it may be, it simply sucks in terms of the actual implementation, as it has loads of functionality that breaks when that shouldn't have been a possibility in the first place. Every time I happened to investigate issues related to Scalaz, I always ended up with a "WTF were they thinking" moment.

> I'd argue that today, you are better off with the .NET VM, as far as features are concerned.

That's bullshit. Speaking of tail calls optimizations, the bytecode available in .NET didn't even work at all on 64 bits .NET, prior to version 4.5 - that's right, before 4.5 the tailcall bytecode was considered more of a guideline. And Because C# doesn't use it, they never bothered to optimize it, so it has a pretty dramatic performance hit in comparison with normal function calls. And Mono probably doesn't do tailcalls properly even today, with F# being unusable on top of Mono for several years.

In terms of features - for example the CLR doesn't optimize virtual method calls. This is killing dynamic languages, or static languages that diverge from the C# OOP flavor in terms of polymorphism. IronRuby was never even close to what JRuby could do even when Microsoft was funding its development, simply by virtue of JRuby running on top of the JVM. And now ever since JDK 7 with invokeDynamic, the performance boost is so amazing at times compared to Ruby MRI, that people are running apps on top of JRuby for performance reasons ;-) The JVM for example can inline virtual method calls at runtime and can de-optimize those call sites in case invariants change or in case it notices that there are no performance benefits. This is something that really few other VMs can do.

invokeDynamic is amazing. It provides a way to override the default method resolution that the JVM does, while still benefiting from the same optimizations that the JVM does for normal method calls. It even has benefits for static languages such as Scala, for dealing with closures and Java 8 introduces a facility for initializing a value that can afterwards be treated as a constant, so there are big wins ahead for Scala in terms of performance for things like "lazy val", or structural/dynamic types and others.

Functional languages use a lot of persistent data-structures and persistent data-structures are by their nature wasteful in terms of short-term junk. You need a really good garbage collector to not suffer from this and the JVM really has the best garbage collectors available. You should see what it can do in a server-side environment with server instances being hit with thousands of reqs/sec per JVM process of real traffic. I have and it's freaking sweet.

Also, it's actually good that Java's generics aren't reified. Reification is only needed for languages like Java in which the type system sucks and stays in the way for more expressive/advanced type systems. Language implementers have to pull off a lot of tricks in order to work around CLR's reified generics. F# has 2 generics type systems in the same language, as Hindley-Milner can't be piggybacked on top of CLR's reified generics.

.NET still has some niceties, like stack-allocated value types, which is sweet if you want numbers that diverge from the standard primitives offered and to avoid boxing (and JRuby suffers a little because of this). But btw, here's another thing that the JVM can do - it can do escape analysis and for example it can decide to allocate certain short-lived objects straight on the stack if it sees that those objects don't escape their context.


Agreed, in fact what's surprising is that anyone thinks it's surprising that the JVM with its billions of man hours and primary usage in mission critical finance/banking/etc is anything but one of the most performant, scalable, robust, well-tooled platforms around.

>Aside from terrific performance, the JVM gives you the best concurrency platform out there (though not the easiest to use)

Though I'd probably still reserve that accolade for Erlang OTP/BEAM.

Though I'd probably still reserve that accolade for Erlang OTP/BEAM.

I would absolutely not. Erlang/OTP/BEAM might be the best distributed computing platform (though Akka is making huge inroads), but Erlang is actually a pretty terrible at single-box concurrency.

Erlang has one concurrency primitive - message passing. Which is great, but it's not always the right one.

Consider a a producer process which solves a PDE or does a big Bayesian computation (output is an Array[Float] or Array[Double]). You have consumer processes which read from the array and compute sums over subsets of the elements.

In Erlang you are just passing around copies of arrays. In the JVM, you'll probably have a single mutable array. You'll either wrap the appropriate calls in arr.synchronize {...}. Or you can use memory barriers and let the consumers freely read from the array, and invalidate their computation if the producer wrote to the array between the start and end of their read.

I've been using Java since the 90s. The JVM is a pretty solid piece of engineering, but your post is pretty heavily loaded with hyperbole. There are plenty of other excellent concurrency platforms for example Erlang, Go, even the. NET CLR.

Is there any chance you could briefly enumerate some of the things that make the JVM's approach to concurrency so strong? I'd be interested.

It's not the approach, but the capabilities:

1. State-of-the-art garbage collectors, which enable good implementations of lock-free data structures.

2. Excellent implementations of lock-free data structures (like ConcurrentLinkedQueue and ConcurrentSkipListMap) and other concurrent data structures (like ConcurrentHashMap).

3. A state-of-the-art work-stealing scheduler (ForkJoinPool), excellent for both parallelism (as used by Java 8's streams) and concurrency.

4. A cross-platform memory model specifying memory visibility across threads.

5. Access to CPU concurrency primitives like CAS and memory fences.

These building blocks are a great foundation for any concurrent application.

Thanks - I use Java all the time - but sometimes I find knowing which data structures to turn to in a given situation tough.

That's true for any language, and any platform. The language can't save you from having to, at some point, understand how to properly engineer software.

Grab a copy of "java concurrency in practice", it's my go-to book for when I've got a tricky concurrency problem to solve.

Could you please elaborate on #5? What you mean there is the fact that AtomicInteger implementation is actually using this primitives on your target platform, correct?

It's more than that. AtomicInteger's implementation uses JVM intrinsics which are calls to methods in the sun.misc.Unsafe class, that, when JITted, are replaced by a platform specific machine instruction (where available), such as CAS or a memory fence.

Do you have more info on the cleanup in Java 9? Will they remove some deprecated methods then?

This talk has some good (and official) information: http://parleys.com/play/52549d02e4b0a43ac12124be

How do deprecated methods affect you? Just curious. Maybe I'm missing something.

In my opinion, they don't. If you use an IDE like Eclipse where deprecated methods are clearly marked by a strikethrough and marked with a compiler warning, I don't see the big deal. And the bonus is that old code still compiles with new versions (and there is something to be said for backwards compatibility, a la "This presentation is not compatible with Keynote" discussion from a few days ago)

Methods are marked as deprecated when they're planned to be removed in the next version.

That's the story that gets told, but how often have they actually removed something after deprecating it? Does anybody have a single concrete example of a method that actually went away?


I don't believe they have ever removed a Class or method from the JDK... Thread still has all of those super-unsafe or non-implemented methods in it (see: stop(), destroy() etc.)

I think part of the reason for this ultra-conservative approach might be that alternate JVM implementations could in theory have well-implemented versions of deprecated methods such as the above-mentioned Thread ones.

No, they (Sun) could not care less for alternate JVM implementations. The reason for that ultra-conservative approach was that they were hell bent on keeping compatibility.

System.getenv was deprecated (in 1.1?), and then replaced with an implementation that threw UnsupportedOperationException (in 1.2?) because it was considered to be non-portable.

Later they saw sense and re-implemented it and un-deprecated it.

What is best practice when it comes to Java GUIs?

Would you recommend Java for building cross-platform desktop apps with near native UI performance?

The IntelliJ IDE looks great but most Java desktop apps I've come across just look and feel weird. Not sure why there is such a big difference.

You have probably encountered the occasional Java desktop app, without realising. If you can't easily tell it is Java, the development team have done a good job.

Two of my company's three products are a Java desktop app for Mac, and they look and feel like typical Mac apps.

Best practice? IMO you should spend significant time on the GUI making sure it feels native. Otherwise, Swing is still about as good as it gets for Java GUIs. JavaFX is supposed to be more modern and superior, but lacks the large-scale support and third-party component ecosystem that you find the Swing. Although I'd be mighty pleased to be proved wrong on that one!

>You have probably encountered the occasional Java desktop app, without realising. If you can't easily tell it is Java, the development team have done a good job.

I've never seen any Java desktop app that I cannot easily tell it's Java. With most of those apps, even on i7/16GB/SSD systems, you get laggy behavior with Swing and the GC. And SWT still has the "uncanny valley" look going.

Usually because the said developers are too dumb and do everything on the UI thread.

Yes. And things are a lot better now, I remember using IBM WebSphere UI tools (written in Java) circa 2004-5.

It took several seconds of whited-out buttons and stuck UI for every CPU intensive operation -- all on the same thread. And that was from IBM, and from tools that you paid for a small fortune.

Java as a desktop front-end language is dead. Sorry. JavaFX is a sad attempt at trying to re-live it, and no one outside of enterprise environments that are pure JVM shops are attempting to use it.

Actually, no, we have used it for a decade and continue to do so, because it is a reasonably clean and performant UI framework that gives us great control and pretty decent platform-native look and feel.

I challenge you to do anything that is first-class profession UI/UX experience in Java, and not want to tear your eyes out in the process. Try building something Aperture, Keynote, etc in Java. I don't know what you're building but my guess is it isn't 'beautiful' or innovative UI.

True, but how many of us programmers either want or need to do that? Less than 1% I'll bet. For the rest of us, Swing works just fine, and it's a whole lot better than some of the other UI toolkits out there.

Except basic interfaces can still be done with things like iOS. If you're going to take the time to build a UI framework, it shouldn't specialize in being craptaculuar.

I'd also venture to say a lot more than 1%. Modern world (finally) recognizes that design/experience are core to any product, enterprise or not. That's part of the reason there's a whole new breed of funded enterprise companies out there -- they're taking lessons from the web/apps and applying them to replace old-school solutions. [I'm personally hoping more people recognize this need for developer tools which typically are the worst offenders of all, particularly on the database side.]

Part of having a good framework is what allows apps/applications to excel -- it helps you raise your own bar because the tools are just so much better that nicer UI/UX can be had without being a nightmare in code. That's a win for everyone.

it's just pining for the fjords.

More seriously, as a recent example you will find that what bitcoin.org offers you as the first option for a wallet (multibit) is written in java.

That may not be mainstream, but it's definitely not the classic enterprise java shop.

And it looks like it was written in Java. Compare against any serious iOS app, for example.

I've been writing UI code for years, including in Java, .NET, Android/iOS, web, etc, so I have a pretty decent clue about building complex apps in all of these frameworks. Java just isn't a modern environment, and by being cross-platform you end up with an ugly lower common denominator that doesn't have useful APIs for non-trivial designs. iOS is probably the best framework/api out there and even that has many issues (luckily obj-c's categories help you fill in the holes).

JavaFX is now a default platform (supported by Oracle) for developing desktop apps. It replaced the clumsy Swing and is showing a lot of promise. http://www.oracle.com/technetwork/java/javase/overview/javaf...

How widely is this adopted? FX is one of those tools I'm a little leery of because of the possibility it may be abandoned by Oracle if not enough people use it.

What is the case for desktop apps these days vs web apps? I would love to mess around with JavaFX but really can't come up with a compelling reason to use it.

If you want to interact with local hardware/storage media, native apps are still easier. "Offline" mode can also be the default, at least for systems that have a local data store. Finally, multicore CPUs may be theoretically exploited with web workers, but it's a lot easier to just spin up a native thread in your Java code.

Downsides are all the usual ones, of course: updates don't happen automatically, you may need some sort of licensing/DRM if you want people to pay for your application, and your testing story is a lot more complex. (Plus: look-and-feel on various platforms, reverse engineering is that much easier, etc., etc.)

Offline + sync, and higher performance requirements are my two use-cases for desktop apps.

In theory, the Android runtime environment could be ported to most desktop environments. I have seen Dalvik running on Windows 7. I used to be CTO at a company that developed an Android runtime for WebOS. You might infer they could do the same for similar platforms. Jolla has demonstrated Myriad's similar technology running Android apps in Sailfish. So while there isn't as cleanly defined boundary between app runtime and OS as with JavaFX, which is designed to be cross-platform, in practice it is possible to move the Android runtime across platforms with good results. It should even be possible to put Android apps into realizable windows in desktop environments.

There is a lot to be said for taking an environment with a big following and making it cross-platform vs making a cross-platform environment and hoping for adoption.

Have a look at SWT. It's the best way to do Java UIs IMO. I don't know why it isn't more popular. It uses the native UI kits internally, so it feels and is 100% native.

There is more to a native ui (common spacing, font usage, interface patterns) than just swapping out the underlying widgets.

Exactly. Try using SWT to do anything like CoreAnimation on the mac with either similar programming ease or buttery results. There's a reason why one should go native for anything beyond a database viewer.

100% native on Windows maybe (and even there it depends on the Windows version). On the Mac it's like a foreign object.

And that's for the more basic widgets -- more advanced widgets have custom implementation from primitives in SWT, so they are hit and miss with regards to native look and feel.

You might be interested in Nifty: http://nifty-gui.lessvoid.com/

It's hardly any "best practice" or "standard", but it looks like people are managing to ship projects with it. Performance is reasonable; on the inside, it's openGL via lwjgl.

Another option is libGDX: http://libgdx.badlogicgames.com/

Their presentations appear to be oriented largely around games, but the parts could be used for a desktop application just as well. There's a number of mobile games in both the app stores using it.

I agree that the JVM is pretty awesome and will only improve (lots of money is bet on it after all) but I think BEAM may fulfil some of the items on your "awesome runtime" list :)

No, actually, Java is a really bad language.

It has a very complicated type system, but doesn't even allow you to express things like function composition or generic sums at the language level.

Its syntax is stunningly verbose (e.g., no map literals; only now adding lambda literals; no type synonyms; no operator overloading).

There is no macro system or method_missing or any other way of really extending the language, except the ugly, unsafe reflection system ... so now all the libraries (Spring, Hibernate, etc.), use annotations and reflection to modify object behavior at runtime.

> It has a very complicated type system, but doesn't even allow you to express things like function composition or generic sums at the language level.

Yeah, sure, it doesn't have Haskell's . or algebraic datatypes, just like lots of other languages. I'm not sure what's complicated about the Java type system, but I suspect you're trying to say you don't like subtyping. Moving on...

> Its syntax is stunningly verbose (e.g., no map literals; only now adding lambda literals; no type synonyms; no operator overloading).

No map literals, but Guava has leveraged generics in a brilliant way to reduce the duplicate declaration of types. Also, it brings a little bit of functional-style goodness with transform/filter. It turns even JDK 6 into something you can be productive with. I'm not sure the lack of type synonyms is really an issue, the type signatures are rarely complex enough that you need to obfuscate them. On the other hand, I'd give somebody else's right arm for an equivalent to newtype and deriving.

> There is no macro system or method_missing or any other way of really extending the language, except the ugly, unsafe reflection system ... so now all the libraries (Spring, Hibernate, etc.), use annotations and reflection to modify object behavior at runtime.

Not to forget proxy objects and interceptors. But yes, Java could definitely use a macro system.

But you're missing the elephant in the room, the existence of null. The bane of every Java programmer, dreading NPEs at each function call.

Checked Exceptions and null. I write a lot of Java and I generally enjoy the language, but those two things; if Oracle could fix those somehow I would be extremely pleased. I'm so tired of writing null checks and I hope Optional<T> is not the final answer since it too can be a null due to programmer error. I am really worried about Optional getting abused in Java 8...

Actually, I waffle on checked exceptions; it seems every 8 months or so I have a different opinion of them. Right now they suck.

> Checked exceptions

It always bothered me that Java forces me to explicitly handle/rethrow exceptions, yet happily overflows my ints without batting an eyelid.

I like checked exceptions in certain situations. I generally dislike the checked ones that come with Java ^1, but it can be very useful to create your own. I had a situation where I was interacting with an API that would sometimes fail over things I could not control. But, the code responsible for interfacing with the API didn't have the context for handling those errors.

Initially I threw a Runtime (ie: non compile time) exception. After going to production I realized that these were bubbling up to the UI and giving the user very intimidating error messages. So I changed the exception to a Compile time exception and then the compiler caught every place I let the error slip through to the UI. In my opinion it saved me a lot of time and made my code easier to maintain.

1: EG: Who is Java to say that this IOException should be handled in code? Perhaps this IOException should not happen and requires a developer's intervention.

InterruptedException is the worst. I know that I'm not calling Thread.interrupt() so why do I need to handle that case? It's already hard enough to reason about multithreaded code without worrying about future-proofing it for some case where it's somehow convenient for another developer to use Thread.interrupt().

I used to think checked exceptions were mostly an annoyance. Then one day, when working with a library doing I/O in Haskell, I realized that I couldn't pattern-match on whatever exceptions it may throw because I didn't know what they were and the type system was no help. Since then, I learned to live with the verbosity.

I'm the same way with checked exceptions. Right now I am in the pro-camp... but just give me a little bit. I am about to start a greenfield jvm project so I think I will be anti soon... but once its mature and I'm in bug fix mode I'll be heading back to the pro-camp.

  I'm so tired of writing null checks ...
Could the null checks of Java be compared to the ones used in C#? My C# code is often littered with ternary operators to deal with null values. And that's still not as safe as the Objective-C approach where one can just send messages to nil[0] which is really awesome imo.

I guess I kinda wonder if I could avoid the null checks in C# somehow ... I figured using a design by contract approach might be used to reduce the null checks somewhat.

[0]: http://stackoverflow.com/questions/156395/sending-a-message-...

> not as safe as the Objective-C approach where one can just send messages to nil[0] which is really awesome imo.

It's definitely NOT awesome. This stupid behaviour causes bugs all the time as you think you're doing an action but it's actually a no-op because something else failed and you get a nil. An NPE is awesome - it crashes immediately and you know exactly what is wrong. A silent no-op is the worst thing to debug.

Have you found C#'s null coalescing operator useful in these situations at all? I've found it to be quite handy.


> I guess I kinda wonder if I could avoid the null checks in C# somehow

Without seeing your code it is hard to say, but using an object extension might work?

On many occasions I've used object extensions to hide checking code deep inside the extension.

C# really got that feature right.

Can you show an example of how this can be done?

+1. If only they had introduced syntactic sugars for nulls, like user?getAddress()?getStreet(). It just doesn't have to be so painful. Writing functions used to be one of them and I'm happy it's solved.

FWIW, I have found using findbugs and @Nullable/@NotNull to be a blessing.

> Checked Exceptions and null.

Let's not forget about type-erasure generics. And the existence of arrays. And the fact that people still use arrays.

> Let's not forget about type-erasure generics.

Type-erasure generics are a fortuitous platform decision, because its what enables languages on the platform to have a good interop story while still having a more robust type system than Java does -- case in point, Scala, and why the .NET version died.

Exactly - checked exceptions is more of an policy / code style decision, null and NPE - roughly the same and in the end your spider sense just knows where to expect it.

But type-erasure of generics - that's the decision with which we will need to live till the end of time.

  - no multiple implementation of same generic interface
  - http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs
  - small performance hits..
  - casts
  - a lot more but I'm just sleepy right now.
I use and like Java, I love the backwards compatibility which it has - but there are times when crust can be removed with scalpel - and if not, you will need an jackhammer later.

I really don't have a problem with erased generics for the same reason a poster below pointed out.

> Checked Exceptions and null

I hear you.

> I'm not sure what's complicated about the Java type system

I assumed this was a reference to the unequal handling of "primitive" types vs Object types, with only the latter being able to be used with generics. Except for the weird "dual" object types which sortof are and sortof are not equivalents to the primitive types (int -> Integer, etc). WHich for methods needing to take actual primitives leads to having to do abominations of repetition such as http://www.docjar.com/docs/api/java/util/Arrays.html.

Some other bad things (not necessarily "complicated" but it does complicate the code that needs to be written):

Enumerations all have to have the same constructor params and therefore the same "shape". SOrt of defeats the purpose of enumerating ALTERNATIVES, I would say (this is part of the lack of sum types that was mentioned, though).

Others mentioned nullability. Some other things I didn't see others mention:

Botched covariance of arrays which leads to runtime failure where compile time should have been sufficient, http://k2java.blogspot.com/2011/07/parametrized-types-and-ar....

Some other minor things, such as botched clonability system, where Cloneable is a "marker" interface that doesn't tell you whether some type is really cloneable, a bizarre unforced error where a simple interface (you know, with an actual method called "clone") would have sufficed.

Optional<T> in jdk8 will help with null:


But without a pattern matching system, optional is still half of what it is in, say, Scala.

Why would you ever pattern match on Option[T] in Scala? In all my code, I do either:

    optionalF.map( _.whatever ).getOrElse(fallback)
or perhaps

    (optionalF <+> optionalFallback).getOrElse(finalFallback)
For those unfamiliar with <+>, see here: http://www.chrisstucchio.com/blog/2014/handle_failure_with_p...

I think that's a pretty extreme position. First, it will run a lot slower than the pattern matching alternative:

    optional match {
      case Some(x) => whatever(x)
      case None    => fallback
Second, I find the pattern matching code much clearer. Sure, it's also longer, but clarity trumps everything.

map / getOrElse is standard in all the Scala code I've seen. Abstracting over the monad is also a pretty big win that has made some big refactorings painless for me. Pattern matching is really only used by beginners IME.

Well, then maybe the beginners do it right? You have not argued against my two points: It's much slower, and less clear.

Clarity comes from familiarity. It's not an objective measure.

The speed benefit is well known, as is the corollary, premature optimisation. I expect checking for null is even faster if speed is the main concern. It's an engineering tradeoff, just like making the abstraction to a monad (or monad plus). In the normal course of events I'm more concerned about flexibility than performance and would prefer the abstraction.

Isn't map/flatMap and orElse enough, if only for Optional?

It's not enough for compactly expressing imperative logic. In Scala:

  resultOption match {
    case Some(x) => println(x)
    case None => println("error")
Without pattern match:

  if (resultOption.isDefined) {
  } else {
The .get is the problem.

There are several ways of doing it concisely with the Java Optional

  import java.util.Optional;

  public class Scratch {
      public static void main(String... args) {
          Optional<String> foo = Optional.of("foo");
          Optional<String> bar = Optional.empty();


          foo.map(Print::print).orElseGet(() -> Print.print("Error"));
          bar.map(Print::print).orElseGet(() -> Print.print("Error"));



      static class Print {
          public static <T> T print(T val) {
              return val;

Java is not a bad language. It was written as a reaction to C++ - a simpler, more consistent systems programming language. In that regard it has been wildly successful. It doesn't really look like a dynamically typed scripting language because it was never trying to be one.

You pick a bunch of language flavour / syntactic sugar and say that Java is bad because it doesn't have those. Personally I like it because it doesn't have things like operator overloading. These are you own preferences, not inherent flaws with the language.

This. I realize the perl people love to have twenty different ways to do everything, but when I'm trying to get maintainable code out of an average team of programmers I don't mind the verbosity and I don't mind the lack of cryptic language features.

The original java architects took operator overloading and the macro preprocessor out for a reason - you can end up with orders-of-magnitude more ugly code if those features are abused.

I was a C++ programmer for a very long time (and a C programmer for a long time prior to that). The abuses of 'helpful' features like operator overloading that I saw in C++ code would be enough to make a grown man cry.

... and also this makes Java a great choice for large distributed teams of programmers of different levels of expertise.

> Its syntax is stunningly verbose (e.g., no map literals; only now adding lambda literals; no type synonyms; no operator overloading).

I can see both side of this. My favorite language to work in is Perl, which is loaded with all kinds of little context sensitive literals. But Java "the language" is pretty quick to pick up and get working with if you're already familiar with another Algol family language, and you can usually read other people's code without too much fuss because the language doesn't support all sorts of ways of writing something.

But on the other hand, you do end up with lots of lines to do something that should be relatively few lines if a more context specific syntax was supported. For example, the last time I worked with Java, code was littered with a half dozen lines of Iterator mess every time you wanted to go through some collection, the new for syntax is very very nice...but there's still little hard corners it's not that well supported in, like maps, because the underlying structure of the map means I have to build some temporary object to handle an item on the map in the loop...even though the map collection I'm using is in the standard library and should be part of the language via some syntactic sugar.

I'm still stunned that operator overloading isn't supported, I have a few use-cases already where that would be very helpful.

What is complex about the type system?

I'm guessing he's referring to wildcards (http://cseweb.ucsd.edu/~atl017/papers/pldi11.pdf) and the fact that the type system allows this (which isn't really a complexity, but rather a deficiency):

Object[] foo = new String[1]; foo[0] = new Integer(4); // exception thrown here instead of a compile error.

Go work with C++, and you'll pine for Java.

And go work with C# and you'll pine for nothing.

I've used all three and after a few years of C#, the other two are just a distant memory.

Which is heavily windows focused, which is non-starter for a lot of devs. Sure there is Mono, but it does not have nearly the man power behind it that .Net and Java have.

And go work with C# and you'll pine for nothing.

Except any worthwhile platform where you're not a second class citizen.

> And go work with C# and you'll pine for nothing.

If that was true, F# wouldn't have happened. (Nor IronRuby/IronPython). Even people who like the .NET platform often pine for something better for the task at hand than C#.

I did, but then javaagent and JMX pulled me back because hooking to runtime in .net sucks.

This sort of reaction is surprising to me. Java has been a useable, performant language for some time now. The tooling is excellent, the JVM is astonishingly good, and it will run circles around Python, no less Perl. I don't think many of the arguments against Java are based on how it works once you've written it, but rather to the horrendous verbosity, class-explosion-as-a-design-pattern, painfulness to read (not debug with an IDE, which is easy, but to actually read Java code), and so on. I'm not a Java developer by trade, but I'm surprised that other people are surprised by Java being high-performing, and the JVM being a good platform. I mean, Clojure Scala and Groovy all run on the JVM, and we talk about them all the time!

Of course you have to understand in my context I've really come in close intimate contact with Java twice. The first time about 14-15 years ago when the JVM was pretty doggish. I think it was Java 1.4 or 1.5. I don't think Eclipse was even out then, and the first version I remember seeing was so dog slow at the time compared to Visual C++ that I remember just writing off Java entirely.

To my surprise it stuck around in Enterprise spaces and I ended up running a team that ported a pretty large-ish Perl project (about 20k lines of Perl) into a piece of Java middleware. I didn't do any of the coding, but I knew the Perl bits inside and out so I knew what kind of testing and performance to expect and getting the Java port up to 1/3rd to 1/2 the performance of the original Perl was a pretty big challenge at the time. This was about...8 year ago. But to the credit of the team and I guess the tooling, they were able to get the port done remarkably quick.

So I've been pretty surprised to see that Java code can get fast, really fast. I've also managed to bang out some pretty slow code if I wasn't paying attention. For my latest touch into it, I ended up spending a week just benchmarking various collections to see how they actually worked under the kind of real-world uses I'd be putting them through (vs. what their big-O sheets claimed) and came away with a set of practices for me to get going with.

I've also had to come to terms with benching code a bunch of times to give the JIT compiler or whatever runs under the hood in the JVM some time to optimize, the first few runs are invariably much slower than run 1000.

> painfulness to read (not debug with an IDE, which is easy, but to actually read Java code)

This is incredibly important and I never see any Java advocate addressing it. I _do_ see tons of people pointing out how easy it is to automate refactoring, and then they leave dozens of ugly, poorly-thought-out methods lying around...

The problem is that there are two major kinds of "reading code".

There's (A) the brief pass you do to get the gist of what a class/method does, and (B) the deeper pass when you try to build a mental model and step through bits of code in your head.

While Java's verbosity does harm skimming, it also aids targeted comprehension, since it is easier to see the "one right behavior" that code has. Fewer sneaky surprises, leaky abstractions, weird type coercions, inferring which class-interface the designer intended to target, etc.

As mentioned already, the other big advantage to explicit-ness is all the static analysis the IDE can do for you.

Verbosity adds noise (redundant information), or information that is usually redundant, so you get used to it, so when you see the ~same pattern again, you skim over the things that you think are the same. But then sometimes it isn't quite the same, because of a bug or because the for loop does a decrement rather than an increment, which is lost on you.

Finding the balance between terseness and having a little bit of redundant information is of course very hard.

> I mean, Clojure Scala and Groovy all run on the JVM, and we talk about them all the time!

5 years ago those 3 languages were the talk of the town for alternate JVM languages, but things change. Scala's pulled way ahead of the pack, Clojure's consistent, and Groovy's on a downward trajectory, following in Beanshell's and JPython's footsteps. Eclipse users are drifting into Xtend, and IntelliJ users may look at Kotlin more. JDK 8's Nashorn is likely to scoop up those who just want to write quick-n-dirty's manipping Java classes.

With groovy being pulled more into use with spring and great test frameworks like Spock, I see more groovy use paired with java not less.

Scala is the interesting one I'm interested to see if a simplified type system can be introduced ala http://www.infoq.com/presentations/data-types-issues

> groovy being pulled more into use with spring

Within the Spring Framework 4.0 Reference [1], the Spring Expression Language takes up all of chapter 7, whereas Groovy takes up little section 28.3.3 only, with only one use case presented. Your statement didn't have any specifics, only sales adjectives like "great test frameworks."

[1] http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-frame...

I've seen very little interest in Xtend in general.

There are warts in the standard library to be sure, but many of them have already been filled in by third parties like Apache Commons, Google Guava, and Joda-time. I'm sure there are others I'm not thinking of.

If you aspire to make Java into the type of language we would arrive at if we redesigned Java from scratch today, it's not just a matter of adding good features but also removing bad ones.

For example, you'd go directly to Joda-Time or JSR-310. Date and Calendar wouldn't be present at all.

Whether Java should break compatibility to remove all the old cruft I'm not sure. The benefits of the cleaner design might not be worth the costs/inconvenience.

I'm glad you added that last line, because that's basically the whole story. Java is /very/ backwards compatible, and it's got round the...errr...quirks of the early versions by having a massive ecosystem of alternative implementations. Some of these (like Joda-Time) are good enough to get widely accepted as the 'correct' implementation. I don't think anyone will argue when you say that that throws up some barriers to entry, but they're not massive barriers, the standard library does still work. Not having to rewrite your code every six months is much more important.

Is there any major language out there that actively removes old/bad parts of it's standard library?

None that have been successful, and this is the nub of the problem.

It's like Soupstrain said: there are only two kinds of languages: the ones people complain about and the ones nobody uses.

A side effect of success is having a large body of existing code to consider when making changes.

Scala? It's still a very young language, though.

Oh, but it's introduced plenty of quirks of its own, which will have to be painfully removed down the line. Odersky himself is trying to redo and simplify the type system with his Dotty project.

What have they removed from the standard library? Just curious.

It's more a case of replace than remove...

Just compare the ScalaDoc of different Scala versions.

Things which come to mind (comparing roughly 2.8 (released 2010-07) to 2.11 (released 2013-03)):

Classes (just from the top-level scala.* package):

  - Application
  - Cell
  - cloneable
  - CountedIterator
  - NotDefinedError
  - NotNull
  - Responder
  - serializable
Complete packages:

  - scala.actors and subpackages
  - scala.collection.interfaces
  - scala.concurrent (still exists, but its contents have been replaced completely)
  - scala.dbc and subpackages
  - scala.mobile
  - scala.reflect.generic
  - scala.swing and subpackages
  - scala.testing
  - scala.text
  - scala.util.automata
  - scala.util.continuations
  - scala.util.grammar
  - scala.util.logging
  - scala.util.parsing and subpackages (includes parser combinators and JSON)
  - scala.util.regexp
  - scala.xml
(This of course doesn't include things which were demoted from scala to other namespaces like scala.util, scala.runtime, scala.annotations ...)

The list is certainly incomplete anyway...

Agreed ...and jdk8 includes what was effectively joda-time (jsr-310) now.

projectlombok.org also makes a lot of the language syntax ugliness quite bearable.

The Lombok stuff is pretty nasty, all kinds of hacks to hook into the compiler internals in unnatural ways. If you want those features just use a language which provides them, rather than awkwardly bolting them onto a language that doesn't.

If you like lombok you might also like the Autovalue plugin from Google: https://docs.google.com/document/d/1THRUCIzIPRqFSHb67pHV8KMb...

jdk8 completely breaks the entire value we get out of using joda-time, namely, that instants are unambiguous. It actually recommends using time and date without time zone.

It doesnt recommends using time and date without time zone, it recommends using the right class for the right job. And sometimes the right class doesnt include a timezone

Suppose you have a webpage asking users for their birth date. What data type do you store that value in? Hint: You aren't going to prompt the user for the time zone they were born in.

Could you elaborate on this? I thought that JSR-310 and Jodatime were supposed to be nearly identical. Why would they introduce such a regression?

They thought they could improve on Joda Time while at it. It's java.util.logging all over again (sadly).

They in this case happens to be the original author of Joda Time.

Filing in the holes is nice, but without actually making it a design choice java embodies TMTOWTDI more than perl ever did.

For many common tasks there are 5 or 6 different standard library calls that seem to do the same thing, but 4 of them are to be avoided at all cost, but there's no depreciation tag and the official javadocs don't contain any pointers to the newer classes.

Can you give some examples of standard library calls that are to be avoided at all costs but aren't @deprecated? Curious to know if I'm guilty of using them.

Oh rubbish. What utter FUD.

This just isn't true.

Yeah, and I've already come across most of those. Integrating lots of that stuff into the standard libraries that Java ships with would be exactly what I'm thinking of...and jettisoning all the broken GUI frameworks and such. And cleaning up the disaster pile that is I/O. I mean, I think there's still stuff sitting around in javax.* from when I last touched Java 14 years ago. I thought that was supposed to be the experimental branch where things might change without warning? Let's clean that up.

I know most IDEs just ship with all that stuff included, but I've found it makes packaging up things to give to somebody else a little more complicated than I'd like...which would be resolved in the standard libraries.

In javax, the x stands for extension not experimental.

I was going to reply with exactly the same thing, and I'd add slf4j.

Because God knows, Java needs another logging framework. Seriously does ANYONE get any additional value out of the morass of crappy logging systems out there over and above System.out.println? Log4J is PARTICULARLY brain-damaged, with its refrain of "ooh, someone put a log4j.xml in their JAR (one of hundreds), that beats your log4j.properties.". Or SL4Js amazing performance of "1.6 doesn't work with Scala because of ambiguous varargs". Or who can forget the incredible log4j logfile appender with the global lock around the file I/O? Not to mention the interactions between SLF4J and org.whatever-it-is-this-week.Jetty's built-in crappy logging facade.

Really, NEVER has so much effort been spent for SO LITTLE REWARD.

Yeah and I don't get why the loggers default to noop when they're not configured correctly. Here's a typical scenario:

I'm deep in the zone, half way through fixing something and it's not working. I start up my app and realize log4whatever can't find its configuration so it defaults to no logging. Now I need to unpop my mental stack all the way to switch gears so I can fix this logging configuration issue because for all I know the key to my problem is in the log message that log4whatever hides when it's in noop mode. Why not default to as verbose as possible?

From what I can tell, the majority of these crappy Java logging frameworks are made by this one guy who keeps on screwing up. Eventually he abandons ship and starts over again. log4j, logback and slf4j are all by the same guy.

Never had a problem with slf4j on top of log4j. By the way, I use DEBUG in development and INFO in production. The ratio of logging messages between the two levels is about 1 for 50. Definitely an useful feature on top of System.out.println. I also change log levels for certain packages because some libraries are too verbose.

Why are you so bitter ?

Agreed. I find it difficult to understand people griping so much about java logging. I know it's not perfect and I wish it were better, but it's really not that bad. Maybe if you come from Ruby or some other newer(ish) language, they only have one logging implementation (I don't really know the state of logging in other languages, so apologies) it's easy to point fingers. You learn your logging, use it, and be done with it.

I am currently in what you could consider log hell with a product based on OSGi. We have been using ops4j logging which has done a fantastic job of adapting the prevalent logging frameworks (log4j, slf4j, logback, and JUL) into the SLF4J API and we don't even have to think about it anymore.

logback is pretty great. I can't take anyone seriously that defers all logging to System.out.println - do you really want the inability to change logging levels between live, test, etc?

Hmm. I've used that feature about once in 20 years of coding professionally.

My production systems don't generally log; they're busy serving (I once worked on a hard real-time embedded air traffic control system where production logging was literally a single bit of information - a logic level that went high when the processor was busy, and low on idle - so we could measure our timing safety margin with an oscilloscope)

Test systems log at debug except for low level packages that insist on ridiculous logging (Hibernate, http client - and both of those have ANOTHER level of hacks to do wire-level logging in addition to the standard stuff).

Logging is just so painful, and not just in Java. Debian switched to rsyslog some time ago and I am still seeing no benefit at all, yet have to learn yet another half-arsed buggy scripting language to achieve simple things like, oh, not having my DHCPD logs showing up in three different files. FFS people.

> Hmm. I've used that feature about once in 20 years of coding professionally.

Try debugging systems for which you can't access the system directly ... say in a product that you redistribute to customers. You will change your tune rather quickly.

For product development, having a good logging system is critical. And, honestly, other than rolling my own over the years (20+ years experience developing and distributing products), the Java logging systems are pretty decent. It can be a pain to get different logging systems to work together and properly configured, and I do wish it were better, but System.out.println() ain't the answer either. When I spend a little time getting them to work right, they do their job. And that is time well spent in my opinion for redistributed products.

> Hmm. I've used that feature about once in 20 years of coding professionally.

Very useful to find out what inefficient code people have generated with Hibernate. Occasionally useful to find out what Spring is doing.

Well said. Logging in java is a complete mess. Logging should be easy, yet it can suck days of your time to get all the various loggers, facades, and libraries to play nice together.

Those warts have been addressed by 3rd-party libraries.

The ecosystem is much better (more stable, higher quality, higher "engineering" effort) than Ruby or Python.

Might not suit to one's taste but we all have different taste buds.

You know I'm not sure I completely agree on this point. As someone that's lived in both the Java and Ruby worlds for a long time I'd say that in a many number of cases you're right. The "shiny object" syndrome is much less of a factor in the Java world and things like backward compatibility are engrained in the culture which manifests itself in the various open source projects. In the ruby world things are simpler to get started with and the surface area of a project is usually smaller and fairly easy to get integrated compared to Java. But ruby projects tend to "rot" much more quickly and aren't nearly as strict about compatibility. That's probably because Rails, the biggest reason for ruby's popularity, is very much about breaking compatibility without a second thought if it means improving the framework. But I've also seen some really well written and tested ruby gems in my time, compared to some java projects... and visa versa.

> I guess what I'm trying to say is it would be great if the language was informed a bit more with what's going on in the dynamic languages space like Go has been. I like how Python is about as clear as Java code is, but it's always seemed a little more quick and breezy to work with. This is something I think Go got right and it'd be great if Java sort of caught onto this.

Java has caught on to this, and a number of the new JDK 8 features reflect this (lambdas and everything related to them, default methods for interfaces, etc.) But Java isn't as unconstrained as a new language like Go is, because its got to support a huge stack of established code as well as making things more streamlined for new code.

Definitely a promising little language. Might make it big in the enterprise.

>If the standard library was cleaned up and the warts were all removed and filled in, even if it broke compatibility (call it Java X or the Latte language or something) I'd be okay with that

this is what groovy and kotlin attempt to do. groovy is backwards compatible with java as well, in most cases java code is valid groovy code.

I'd say Ceylon is the interesting project here - it keeps the JVM but drops the standard library.

(I'm a big fan of Scala - its sheer power is second to none - but it definitely has its ugly parts and many of them can't be fixed as long as it's to remain compatible with the Java standard library)

I've always been reticent to learn these offshoot dialects of languages unless I really needed to. I'd much prefer it if they were treated as syntax experiments, and good ideas from them filtered back into the main language.

It's a mistake to think of one "main" language. There's a limit to what can be fed back into the Java language. Other languages like Clojure and Scala have more than enough going for them and stand on their own merits. I'm seeing increasing numbers of teams relegate Java code to legacy status in favor of newer JVM languages.

The problem is the rate things get filtered back to Java. I started using Groovy when I kept waiting and waiting for new language features. In 2003.

Groovy wasn't production-ready in any way, shape, or form until 2005 when the parser was rewritten in Antlr 2, and even then it took years to clean up bugs particularly those related to the MOP which was added in 2006. The Java 5 features weren't even begun to be added to Groovy until early 2006, and they're still buggy. The only significant addition to Groovy since then has been a @CompileStatic tag in Groovy 2.0 in June 2012, which its main user Grails 2.2 didn't dare bundle until 6 months later, but didn't actually use the static compilation. Grails 2.4, still in development, is the first to actually use any of the static features of Groovy, but with a strong caution in the doco: "Care must be taken when deciding to statically compile [Grails] code." http://grails.org/doc/2.4.0.M1/guide/introduction.html#whats...

> groovy is backwards compatible with java as well, in most cases java code is valid groovy code.

Whenever I read that meme I get damn suspicious about why java code isn't valid groovy code in all cases. Why only most cases? It all sounds like a recipe for spending half a day debugging simple scenarios where things don't run as intended.

To be taken seriously (or as seriously as a language called Groovy can be taken), embrace and extend Java fully, don't embrace only 99% of it before extending. That's what Microsoft tried with J++ and lost a lot of trust with developers that took them a decade to win back.

Its mostly things where the java code contains groovy identifiers, but here is a pretty good list: http://stackoverflow.com/questions/687601/valid-java-code-th...

Groovy isn't attempting to fix Java, it's entirely different. (And it sacrifices type safety--even what of it you get with Java--and performance to do so.)

> And it sacrifices type safety

Groovy is optionally typed, you can have as much safety as you wish.

> and performance to do so

If you use static types, you can use @CompileStatic to get most of the performance back.

Groovy's main user Grails 2.2 didn't dare bundle Groovy 2's @CompileStatic until 6 months after its release in June 2012, but didn't actually use the static compilation. Grails 2.4, still in development, is the first to actually use any of the static features of Groovy, but has this strong caution in the doco: "Care must be taken when deciding to statically compile code." http://grails.org/doc/2.4.0.M1/guide/introduction.html#whats...

Optional typing adds a ton of sand to the gears when you actually are writing code. @CompileStatic requires you to spend entirely too long thinking about what's actually legal to annotate and generally sucks rocks to read and write.

So, okay, you're technically correct, which is every nerd's favorite kind of correct, but writing it that way sucks. Groovy isn't a bad scripting language (or wouldn't be if discobot ever got done), but it's unserious as a Java competitor where Java is good.

JVM is fast these days, indeed. I was playing with Solr lately and was shocked with its speed... Also saw a comparison of HTTP servers lately and the fastest one was written in Java, I think.

> lots of over-objectizing everything

This. This is what I think of when I think of Java.

Object orientation isn't a bad thing per se, but everything should be done in moderation and, well, the argument can certainly be made that Java has gone a bit or two too far.

The problem is not java the lang. It's the java developers. Looks like they moved on to do angular now.

That's a good sign. Y'all JS devs need to learn something from Java community (especially the engineering/quality side) even if you guys have to go through the pain of Java growth (small => medium => bloated => denial => acceptance => cleaning up => shaping up for the future).

Amusingly, I'm undergoing that transition right now from doing mostly JS to doing JS & Java professionally.

I'm not sure how I feel about Java so far, although there are problems that I want to solve in the Java backend at work for future scalability, since the quality of code is actually worse than our frontend code currently.

It's a bad sign for .js devs: trouble ahead.

JS ecosystems in terms of quality, tooling, and engineering is already bad, can't be worse than that really...

PS: No, yet-another-js-library-to-replace-jquery is not considered tooling. No, yet-another-replacement-for-grunt/bower/yeoman is not a good sign of the ecosystems. Java has Maven since 2004.

Maven is horible. Hth

It's awesome and other tools (bundler) are copying it or build on top of it (gradle, buildr, Ivy repo). XML is horrible, not Maven.

Python tools don't even come close. Ditto with .NET NuGet. Find me a tool that can compare feature by feature with Maven and still relevant for a long time.

I've always said: "With Java plus XML, you can have one language for the price of two."

With Java, you write a lot of syntax to get static typing, but it's worth it because static typing! Then you throw static typing away (because now it's to restrictive I suppose?) to use XML files which must be structured a certain unpredictable way or you'll cry at the traceback you receive, and pray your imminent Google search can make sense of it all.

Nobody with any sense uses XML in Java anymore. Everything uses annotations now.

Well, your responses mostly amount to "OMG, I hate Java coders / everything there sucks" etc. Not really insightful.

I partly agree with this.

I'm a systems engineer, but I have to touch some Java code from time to time. I always have an hard time with the amount of indirection an average Java developer can reach. Luckily a few smart guys were hired recently and they have past experience in contributing to the JVM and their approach to the code is completely different and much, much more simple to understand, and since they came onboard the performance of critical parts of our main application increased dramatically with a few lines of code instead of the previous 400 or so.

Isn't it amazing how fast applications can go when they stop doing things they don't need to do?

> I always have an hard time with the amount of indirection an average Java developer can reach.

It probably has to do with the "enterprise" culture that tends to err on the side of overgeneralising things and applying far too much abstraction (Java came into being at a time when the OOP fad was gaining significant traction.) The standard library also being in that style encourages this too.

But things like Java4K suggest that it's definitely possible to do a lot in a tiny amount of code.

Breaking backwards compatibility isn't really an option, but if the compiler and IDE would discourage the use of legacy features that would be best.

Just remove the legacy/ugly methods and packages from the autocomplete process, and warn with recommendations/flag as deprecated. You don't actually have to break anything.

Actually, every IDE warns you if you try to use a deprecated method. They show as strikethrough in your source too.

There are things like http://docs.oracle.com/javase/7/docs/api/deprecated-list.htm... and IDE's know about this.

Problem is Sun^W Oracle hardly ever depreciates anything. There are 21 classes in that list (7 in java.*), out of a total of almost 4000 as of java 7.

You might want to check out Groovy. It's built on the JVM, you can use all the standard library and third party Java packages including stuff off Maven, and you can even just run straight Java code through it. However, at any time you can also drop into Groovy land, and write in a much more concise and functional style. Closures are very common (just look at anything in Gradle), it was clearly influenced by Python/Ruby as far as syntax and type optionality, there's a REPL (groovysh), there's a modern web framework (Grails), all in all it's pretty nice.

Meh, used Groovy for 2 years followed by a year of Grails 1.3.x hell.

Both the language and the framework have likely improved since then, but after switching to Scala + Play there's simply no going back ;-)

p.s. Haskell + Yesod (or Snap) look interesting as an alternative web stack to explore, but otherwise not seeing much out there that would draw me away from Scala land.

Interesting. Scala always put me off, the sytax just seems so nasty. Does that just get better after working with it for a while?

So much better ;-)

There's a learning curve, can't hit the ground running as you can with Groovy, but with Groovy there's a ceiling; with Scala the only ceiling is (perhaps) Haskell and for that you have to leave the JVM.

Languages where you can "hit the ground running" always have a ceiling. If you churn out working code quickly, you're offloading the real work onto someone else in the future. Real world programming, like business, is all about borrowing from the future, intending to default on the debt.

C# is a nice languae. Java...not so much.

Properties, delegates, proper generics, LINQ and so on.

The real problem with C# is that it is still basically Windows-specific. Yes, Mono is out there, but have you actually tried to build a Mono app without using Xamarin? Have you looked at what the Xamarin licenses cost? Once your project reaches a certain level of complexity, you have to pay them outrageous fees. And even with it, it still feels like you're operating something that could keel over at any second. The ecosystem there is just terrible, which is a shame because F# is such a great language.

The thing that makes Java so great as a platform is that there are so many totally reasonable tools that you can just download and use. Eclipse, IntelliJ (community version, which is still pretty good), the myriad of excellent alternative JVM languages, all freely available and cross platform.

A lot of the things you can do with LINQ you can do in Java now there are lambdas and method references. e.g. http://benjiweber.co.uk/blog/2013/12/28/typesafe-database-in...

Properties you could simulate with lambdas now. something like Property<String> name = get(() -> name).set(name -> this.name = name);

You would lose all the existing framework support that assumes getters and setters doing that though.

Some of the generics failure will likely be fixed in 9 (Primitive specialisation). Other things are not as bad as some people think (At least generic supertype params are available at runtime)

That's an impressive proof of concept, but without expression trees it can't quite measure up (e.g. you need to remember to use `.and` instead of being able to use `&&`).

I agree C# from pure language point of view had a better road map and unlike Java which was sort of kind of run by committee did not need colossal consensus from disparate groups for new language features.

JVM vs CLR its a different story - I am hearing Microsoft in negotiation with Xamarin to buy/invest, that may make Mono get feature/implementation parity with CLR. Till then JVM is the only thing close to platform agnostic environment in town.

I would say that C#'s language evolution is too closely tied with the terrible frameworks as well as legacy they have to support.

Lots of things in the library have multiple ways of doing things. Eg File, NIO. Generally if you use the new class you're in for a nicer time.

I agree about the regex literals. JavaScript does it right.

Well you are basically quoting Joshua Bloch of Effective Java fame when he says "please don't abandon the JVM, a lot of work went into it"(My paraphrasing).


I think a simple enough solution would be to introduce raw strings which is how regex is usually done in python.

I've gained an affection towards IntelliJ after having to use Android Studio for some development.

Much more flexible nicer and customizable (from a UI pov) than Eclipse-based IDEs.

One reason I love JRuby.

The ruby language syntax with the power of the JVM and Java library interop.

As far as I am concerned that is a match made in heaven.

What IDE do you use?

Java is the #1 language in the world. It's the best out there, period.


Best at what? You've link to a notoriously unscientific index which counts search engine results. How does that make one language universally better than all others "period". I've coded in Java for most of my career, but the blind blinkered faith in the language within the Java community never ceases to amaze me. It's one tool available among many, look a little further than that single hammer which you worship in your toolbox.

Popularity != Quality

I don't think you can become a popular cross platform systems programming language without being pretty decent.

There is a lose correlation between quality and popularity, but being the most popular language is in no way indicative of being the best language (as the person I responded to was saying).

I agree. I've ran across a few obscure languages I thought would be barren, but found they had exciting new developments happening. It made me realized there's a big difference between the number of language contributors and the number of language users. Most are language users, like myself, who glue a few libraries together and write a little business logic and call myself a programmer. Whereas a language contributor (as I call them) create libraries, development tools, etc. I've wondered if the number of language contributors is roughly equal, within an order of magnitude, across most languages, even the obscure ones. Language contributors add quality to the language, language users (again, myself) don't.

Well I guess the problem with "best" is that you have to ask: best for what? Looking pretty? Running fast? Being elegant? Being maintainable? Getting Shit Done(tm)?

Yeah, it's a kinda vacuous statement I guess :o)

For me, the best part of this release is the fact that the TLS stack has been significantly improved, and is now quite good. The lack of some critical features in Java 7 (e.g., inability to enforce cipher suite order) made TLS effectively unusable.

The list of improvements is quite long, actually:

- Server Cipher Suite Preference

- Strong Server Ephemeral Diffie-Hellman Parameters

- Authenticated (GCM) Suites

- Hardware Acceleration on Intel and AMD processors

- Server-Side SNI Support

- Ability to disable client-initiated renegotiation

- TLS 1.2 enabled by default in client mode

- Clients support Ephemeral DH over 1024 bits

More details here: http://blog.ivanristic.com/2014/03/ssl-tls-improvements-in-j...

And there are more security improvements documented here: http://openjdk.java.net/projects/jdk8/features#core/sec

The DH size support is required for some US gov certifications I believe. Maybe FIPS 140-2 or -3.

Yay!! Java 8 is released!!

My favorite parts:

- invokedynamic : http://stackoverflow.com/questions/6638735/whats-invokedynam...

- Project Nashorn : http://openjdk.java.net/projects/nashorn/

- lambda expressions : http://openjdk.java.net/projects/lambda/

InvokeDynamic came in with Java 7. I've got a large code base here that uses it extremely heavily and it's great, though you do need to do some careful tuning to really make it perform, and then retune when they change the implementation. :-)

Nashorn is said to be high-performance, and I've looked around for benchmarks several times since it was announced, but I still can't find anything but this:


What gives? Wouldn't a real comparison to Rhino and V8 (at least) be interesting?

Edit: strike that. Found someone who ran Octane and SunSpider and compared it to V8 and Spidermonkey: http://wnameless.wordpress.com/2013/12/10/javascript-engine-...

I've been using JDK8 for a while, but no Nashorn on Android keeps me on Rhino. Which is unfortunate. Rhino's a pain.

Android doesn't use Java 8, I believe it's mostly still on Java 6.

Yes, I'm aware, thank you. There are efforts to port Nashorn back to Android.

Nashorn is going to get faster with time. It is not a browser engine so don't try to compare it directly with V8 etc.

> Nashorn is going to get faster with time. It is not a browser engine so don't try to compare it directly with V8 etc.

v8 is not a browser engine either ,it's a javascript engine,just like Rhino. you are mixing up Webkit with v8.

"v8 is not a browser engine either ,it's a javascript engine,just like Rhino. you are mixing up Webkit with v8."

- I think you're partly correct but also confused. Webkit is a rendering engine and yes V8 is a JavaScript engine not a browser engine that was created for Chrome Browser by Google. It's used for Node.JS etc now but it's sole purpose was to make Chrome faster and that is not the same purpose of Nashorn - nashorn is a replacement for Rhino. That is what I'm trying to say.

And Nashorn is supposed to be faster than Rhino... Nashorn and V8 are both JS-engines, why wouldn't you compare them?

Because what you're comparing is Tesla (everyday sedan) vs Ferrari F14T (race car)

When the only thing you care about is performance that is a valid comparison. Besides, Nashorn is fast, was ment to be fast, and they are working on making it faster.

I also like the pluggable type systems: http://docs.oracle.com/javase/tutorial/java/annotations/type...

As noted in your link, invoke dynamic isn't intended to be used for Java developers - it's intended for non-Java languages running on the JVM.

yes, that's the magic of it! You can run code dynamically from other languages.

I'm very happy with the JVM in general, but I really, really, really wish they fixed the start up time. People compile Clojure down to Javascript for command line tools precisely because of this. lein <anything> takes annoyingly long, so I don't do it.

I realize this is not a real concern for them for e.g. servers, but I wish they had some developer- or desktop-specific configuration that would start about as fast as a Python VM. I don't even care if it runs code (a reasonable fraction) slower.

They are working on this. See this talk about the modularization of the JDK in Java 9, which includes bundling of lean Java runtimes: http://parleys.com/play/52549d02e4b0a43ac12124be

Can you please give a use case of a program that a few hundred ms delay during startup would be an issue?

Few hundred milliseconds? I played with clojure a month or so ago and invoking lein repl was ~7.5 seconds.

I never worked with Clojure, but a simple java "hello world" starts and finishes within a second. Same with a simple java Swing UI "hello world" sample. If some application is doing something slow during initialization - it is not the platform itself, but the specific code to blame.

Lein starts a JVM instance for itself, then loads plugins, checks dependencies etc. and starts a new JVM instance for the program if necessary.

Yes, I can confirm this.

Clojure seems like a good fit for tiny projects that are little more than scripts, but the start up time makes them kind of annoying to manually test. Fortunately Clojure does have a REPL.

The best cure to this problem is nREPL. It basically is an REPL server. There are plugins for Emacs (nrepl) and vim (vim-fireplace). With these tools, one may start a user repl and run tests within that. I have written a humble guide to set up Emacs for clojure here: http://gkayaalp.com/2014/01/28/taste-clojure.html#emacs My emacs configuration repository is gone thought; I'm using vim these days.

A JVM with smaller memory and cpu needs and faster startup would make me consider using Scala/Clojure again.

> There are plugins for Emacs (nrepl)

I think nrepl for emacs has been replaced by cider (which still uses nREPL)

AFAIK Cider is like SLIME, big and integrated. Emacs nrepl is just the repl connection, and is usually enough (at least, has been enough for me).

Ok, maybe I'm misunderstanding, but from [1]:

"CIDER (formerly nrepl.el) is the Clojure IDE and REPL for Emacs, built on top of nREPL, the Clojure networked REPL server."

That and the availability of the packages on melpa:

  cider              20140318.... available  Clojure Integrated Development Environment and REPL
And the fact that technomancy's git repository for nrepl.el hasn't been touched in 2 years leads me to believe that cider is the better nREPL choice ;) Be happy to hear that nrepl.el is still maintained and is better in some way than cider, but I don't see cider as being that heavy (at least as compared to SLIME).

[1] -- https://github.com/clojure-emacs/cider

Yes, but that's more of a Clojure problem than a JVM problem.

Practically any command line utility? eg. ls, cat, sort, uniq, ps, what have you.

I'm constantly amazed that make(1) can do successive recompiles of a 50k LOC project in less than a second, while gradle / maven / etc takes upwards of a minute.

Good example, but we have heaps of command-line utilities written in Java. Many complaints but never about performance or start-up time.

For some low-level programs executed hundreds of time per session (like "ls") I agree it adds up and might cause frustration. Java is a bad choice for this niche, but you are not going to write them in Python anyway, aren't you?

PS: Just tested "LS" in Java, less than a second run, I could personally live with that.


If you're curious about the developer-facing changes in Java 8, I of course recommend the blog entry we wrote up last year [1]. It's a bit hard to believe it's been a year.

[1] http://www.techempower.com/blog/2013/03/26/everything-about-...

Superb post! Thanks for sharing.

Anyone know what Google is going to do about Java 8 compatibility on Android? Not being able to adopt lambdas on mobile is a bummer.

Maybe worth a look for you: https://github.com/orfjackal/retrolambda

AFAIK they still don't support all of Java 7 so...

They support "parts" of java7, but not everything.

You can use most of Java 7 but not the new dynamic stuff. I'm told that lamdas will require this feature so we won't be getting that for a while.

This is total speculation, but they're also moving away from the DalvikVM to the new ART runtime. I'm hoping that they're keeping Java 8 in mind as that gets implemented.

They added support for try-with-resources in KitKat, maybe they will continue to add support for new Java features in newer versions?

Apparently Android is not using Java, but something that looks like Java. I bet Google vs. Oracle trial can be attributed to that. :)

Actually they use Java the language, except that the code doesn't run on JVM but on a different VM (Dalvik at this time). Dalvik supports Java 6 and parts from Java 7.

Dalvik is dead. Art is the new king

Maybe in the future, I doubt anyone, except Android developers, even knows about Art.

Art is still experimental and not enabled by default.

Applications are open for YC Winter 2022

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