I also find it fun how Guy Steele had in retrospect the perfect plan for Java back in the 1990s, and it took them 15 years to come around to it:
When I was using it I didn't particularly mind it except for the clumsy handling of functions (i.e. as objects instead of first-class citizens) and verbosity (no automatic accessors, implicit typing, etc). Adding Lombok solved most of these. *EDIT: Except for runtime type erasure of generics which caused (not sure about new Java) performance issues and made certain type operations difficult.
> but the culture around it is what's grown the distaste many have for it.
Having to debug esoteric issues with classpath, Spring, CDI, JPA, Aspect4j, etc. is hell on earth. I've lived that life and have no desire to do so again. Because Java is the lingua franca of enterprise development it also tends to rear its ugly head on modernization projects and rewrites. 80% of the abhorrently-engineered codebases I've encountered in my career were written in Java by body shops (C# and Coldfusion were the runners up).
> The overuse of design patterns, etc.
I'm not an adherent of the design pattern cargo cult but I'm one of four people under the age of 50 that have actually read the GoF book and I do indeed sometimes name objects after patterns described in the book; I typically design components and name them such after the fact as opposed to constructing systems from the ground up using design patterns. Calling a thing that persists comments in a database `CommentRepository` is a lot more useful than calling it `CommentHelper`.
The term "DLL Hell" came from Windows development before it. The Node/Ruby/Python equivalent is getting native libraries to build (node-gyp, I'm looking at you!). I've burned days in Ruby Version Hell and Node Version Hell. Javascript dependency upgrades are a nightmare compared to Java dependency upgrades.
I don't think this problem has gone away, or even improved. It's just a grim fact of life, and Java doesn't deserve special mention.
Getting weird, hard to follow conflicts between different packages on Hackage and dealing with weird compiler hack flags is something that never got fun or easy.
import static example.Library.*;
And proceed to write in your main method var x = someFunction(6, ‘that’);
in a style like C, LISP, or ML. You can write a whole program (like the answer for a HackerRank problem) in a single file. The developers of Java have always respected the ML family and JDK17 incorporates pattern matching, records, algebraic types and and many other features that make functional programming fun.The type erasure problem for generic classes goes away when you use generic methods; type inference works without limitation for generic methods and is great for defining APIs for internal domain-specific languages
any(grammar,you.want(ifIt.parses(ON_THE_LEFT)));
the great thing about Java is a quality IDE is certain to support this programming style.Any complaint that the internal DSL is too verbose can be attacked by the use of code generation which is straightforward to incorporate in a maven build and your IDE. (The LISPer is using code generation and you have to do it if you want to keep up.)
I'm one of the rare people who was writing vb and then c# during the terrible Java j2ee days. Then I got a job in a startup using Java which avoid the 'enterprise' idioms. So my experiences with Java over the last decade or so have been mostly good (except for a foray into Hibernate, never again - jOOQ for life). No crazy class models, no xml configuration, etc...
This looks like a developer simply did not declare proper dependency between classes/beans.
Until Java came around every book on Object Oriented programming (say "C++") had examples such as "Stack", "Queue", etc. In the case of Java you saw people starting to write objects mirroring the business and application domains. People who were trying to use objects in Smalltalk or C++ in 1990 just weren't accomplishing enough that somebody could step back and say "object orientation sucks", rather they were getting stuck and blaming themselves or blaming the tools, rather than the concept.
What people fail to realize is that the enterprise culture is language agnostic.
Before Java we were doing the same with C, C++, VB, Delphi, Smalltalk and whatever 4GLs one wants to dive into.
When Java gets replaced by TechX, the space ship enterprise architects will keep doing what they know best in TechX.
Java has been trending away from this for some time now. A modern Spring app looks nothing like an old J2EE app.
----
Unnecessary opinion: I don't like either, but WebObjects sucks about 1/10th as much as J2EE.
> By the time DOE, now known as NEO, was released in 1995, Sun had already moved on to Java as their next big thing. Java was now the GUI of choice for client-side applications, and Sun's OpenStep plans were quietly dropped (see Lighthouse Design). NEO was re-positioned as a Java system with the introduction of the "Joe" framework, but it saw little use. Components of NEO and Joe were eventually subsumed into Enterprise JavaBeans.
Taken from https://en.wikipedia.org/wiki/Distributed_Objects_Everywhere
You're absolutely right, thank you for clarifying!
https://cs.gmu.edu/~sean/stuff/java-objc.html
Hence interfaces, dynamic loading, reflection and so forth.
Bringing it back to a previous point I made, I met someone who claimed to have helped port over the WebObjects framework from Objective-C to Java, and he claimed that while it's not a 1-to-1, you can fairly easily map a lot of the Objective-C semantics to Java, making the porting process not that hard.
Objective-C related content,
https://developer.apple.com/library/archive/documentation/Le...
Java variant,
https://developer.apple.com/library/archive/documentation/Le...
But, really, watch the talk. It's one of the best conference talks in computer science history.
And reified generics are nice for c#, but a right pain if you want to implement another language on the CLR which isn't very c#-ish.
More recently I'm still not sure why, in a language with an extensive runtime and its own VM, they went with async / await rather than fibers or continuations like go and java. It was probably simpler to implement initially, of course.
Even slow moving java shows that bad decisions have a cost down the road even if the features are unused: there can be monitors on any object to support synchronisation, serialisation similarly lurks around internally.
Async/await work much much better than goroutines for GUI programs, which was still a major market at the time this feature was added to C#. Since there is a single GUI thread where everything that touches the GUI must live, but you do want your application to have multiple other threads, you need to give the programmer this kind of control and can't rely on a more simplistic Go-style green threads runtime.
I believe COM also has some similar requirements, but I am less sure than I am for GUI.
Finally, C# has a lot of influence from the functional langauge community, so it's possible that async/await and Task values were a more appealing solution given those particular tastes.
Couldn't you have the GUI thread on one core, and the "goroutine pool" taking all the other cores, and distribute work on that pool? The model would be a bit more complex than Go, but considering C# is made for a wider variety of usages, multiple models wouldn't be so far fetched.
Isn't that just a limitation of Go since its goroutines all run in the same pool? As far as I know, in the Java implementation you'll be able to create virtual thread pools from regular threads (i.e. the gui thread) and then have another virtual executor for the rest of your program. You'll still have the backend vs gui split but you won't have the entire async await split for the rest of your application.
No one was willing to approve another extension of the old runtime, and a major one at that. If they had already completed the .Net Core rewrite back then they would've probably baked async into the runtime.
Some C# things seemed rather strange (like delegates), some purely cosmetic (like indexers) and there were also things that Java had but C# did not like covariant return types (available from C# 9.0)
*Project Valhalla is supposed to bring it to Java but I wouldn't hold my breath waiting for it.
The code compiles but from time to time it fails at runtime and performance are sometimes Ok, sometimes not depending on the call stack.
[1] https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
class Foo {
int Bar { get; set }
}
Allow you to get/set the value of someFoo.Bar as if it were a public member.
If you want read- or write-only members, you just remove the "set" or "get" portion.
If at some point you need to add logic to the setter, you just do int Bar { get; set { /* setter logic goes here */ } }
You still use assignment syntax ("someFoo.Bar = newValue"), but this syntax is desugared into a call to the setter method. Ditto for the getter.IMHO they make class APIs much cleaner and forward-compatible (on the other hand, if you started with a public member and then need to add a proper setter with some logic, you would break the API).
Also, non-nullable types are a pretty nice way to avoid checking for null every other line of code.
And these are literally just the first couple examples that came to mind.
Non-nullable types sound great, I wonder if this could be introduced to Java in a backwards-compatible way (I suppose it would follow the same path with introducing explicitly nullable types first, though I guess it could be handled using Optionals?).
This isn't the only way of doing it, depending on your language. Python has a completely different mechanism where a class can start with a directly-accessed "y", but in a later version make it a property. (More than one, actually.) Some languages route all property accesses through something you can hook. Some languages simply automatically do what C# is doing here.
Semantically and abstractly, there's no reason to every not be able to override a property access in later versions like that, because it is so darned useful. Unfortunately, performance wise, it's hard to beat a language that guarantees structure layout and guarantees that x.y can be compiled into a single constant memory load instruction, and unfortunately, you can't just wave "compiler optimization" at the problem and make it go away (considered in isolation this seems like an obvious solution but as usual as it starts interacting with all the other features it gets much harder than the simple cases). The higher performance languages have a strong reason to give people ways to get guaranteed direct struct member accesses.
I haven't developed in Java in a long time, but public instance variables were a no-no when I did for these reasons.
This is how I feel about Kotlin.
In 1996, Java was pretty darn sexy. Managed runtimes in a high performance[1] language were an absolute revelation at the time.
It's absolutely true that as it evolved, Java grew to embrace the affects and aesthetics of its biggest customers (Enterprise backend coders). And that's not sexy at all. But at the time? We all thought this was going to be the systems language for the next century.
[1] Almost. At the time this email was written, the first JIT JVM was still a few months out from its early beta releases. But Gates could absolutely see where the wind was blowing.
Java is not the most pleasant language for sure. It started as a dumbed-down as golang was (still is?) for years. It's still catching up with C++ (e.g. see all the Valhalla project discussions on HN). It certainly shows its age. It's not clear to me why so many people are still fixated on Java when solid alternatives have existed for years within the same ecosystem.
Also, if you don't like JPA try JOOQ.
Value types on the JVM have been described as "6 PhDs, knitted together". In C and C++, this is just struct.
> It's not Javascript, where the framework your front-end lead sold you on last week has already been superseded by the hot new thing.
You should stop spreading stuff like that, it's false. React has been the most popular frontend framework for 6 years at this point, and Express the most popular backend framework in JS for at least 8 years. The backwards compatibility of JS is at least as good as Java, ES5 and ES6 were great upgrades (a bit like Java 5 and 8 in a way).
I like Java and I think it's very important. I can say that without feeling the need to dismiss other languages that are as important as Java to the modern world.
But that is regarding the implementation/specification. For the users it will be two new keywords and .ref. It will even ease the language by healing the rift between primitives/objectsz
But Java is a trivial language comparatively, your mentioned complexity is user-generated.
Only if you're defining innovation as syntax and semantics to the language. Java has been the pinnacle and cutting edge of language implementation innovation decades - Sun/Oracle is/was the Bell Labs of VM and JIT research.
The only time I've ever had to use Java was for a computer science class, and I thought it was a solid language (pun intended), but I hated its half-assed attempt at operator overloading.
I think it's a major feature that's long overdue to be fully implemented in Java, because it's already used for some of Java's built-in classes and it's proven useful in many other programming languages.
Most of Java seems very well-thought-out to me, but for some reason they decided to add only some operator overloading, instead of planning ahead more.
I remember hearing somewhere that they were planning on adding operator overloading, but last I checked it didn't look like it was going anywhere.
Java was one of the first language specifications to be written by adults (maybe Common Lisp was the first, but it drives Common Lisp fans crazy to compare Common Lisp to Java, Python, etc.)
Python's operator overloading works remarkably well given that it has a very simple model (always look to the left hand side to decide how to interpret the operator.) C++ on the other hand ought to make anybody skeptical of the idea, but C++ would make anybody thoughtful and sensitive question the idea of computers entirely.
I think ALGOL was first, in the ALGOL 60 Report (https://en.m.wikipedia.org/wiki/ALGOL_60#History). COBOL may have had a good spec around that time, too.
There were older languages with specifications, but those specifications were looser, with languages partly defined by their prime implementation.
Common Lisp in fact, as most lisps, has no support for "operators" in the infix sense at all. If you have a need for a very algebra-heavy portion in your program (say, a linear algebra library), the best idea would be to define a DSL for that particular algebra - especially since this will give you much more control over efficient evaluation than using the built-in evaluation order.
A good example of the limitations of simplistic operator overloading is matrix algebra: A+B•C can be computed efficiently as a ternary operation, more efficiently than doing A+B then multiplying the result by C. Now of course, you can implement this in C++ by having operator+() return some kind of matrix_addition object, and then defining the efficient operations in operator*(matrix_addition, matrix) etc, but that is much more roundabout than defining a simple addAndMul(A,B,C), or an explicit optimizing DSL.
Java has always been in a strange place of not deciding if it wants to be a systems or application language. (The standard architecture is that demanding systems, say video games, are written in both a systems language and a scripting language. A Python coder feels smart when the incorporate, say, number is written in C or FORTRAN but Java’s xenophobia makes that feel like a personal failure. Java is ‘good enough’ for applications programming that you might find something like Spring or Guava gives you all the dynamism you need with less hassle than adding an embedded scripting language like Groovy or Clojure.)
Both can be written in a Java like fashion to start, and have 100% interop with Java (you can mix the languages in projects) so the learning curve is pretty alright.
JDK 17 has most of the good features of Scala and Kotlin.
Scala seems to be designed so that you can write a short book with very fluent and natural looking demos. Make a small deviation from that and there is nothing fluent or natural about it.
Kotlin is OK but isn't sufficiently better than Java to be worth using when any Kotlin dev is going to have to know Java and Java-Kotlin mapping pretty well to use libraries. (It's a similar problem to Typescript.)
Both Scala and Kotlin are sufficiently similiar to Java to provide no real benefit. I'd point to Clojure as a language that is radically different from Java AND that takes advantage of the strengths of the JVM to be worth the cognitive load of having to know both a new and old language to be productive.
I keep reading on HN that "Kotlin isn't much better than Java X". Having used Java and Kotlin (mainly targeting JVM) full-time for 6 years, this doesn't match my experience at all.
Here are some of my favorite Kotlin improvements over Java that I leverage all the time:
* Much improved type system (nullable types, function types, declaration site variance, type aliases, contracts, better type inference, reified function type arguments)
* Local variables are final by default ("val")
* Type-level distinction between read-only and mutable collections (but compiled to Java collections under the hood, so no conversion required when interacting with Java)
* Much improved collection API
* Much improved lambdas (e.g., no pain points w/ mutating variables and checked exceptions)
* Extension functions (incredibly useful in practice)
* Much better DSL capabilities (great for UIs, generating HTML, etc.)
* Lazy properties (more generally: delegated properties)
* Coroutines (looking forward to Java's Loom; by then coroutines will have dramatically improved my async code for 5+ years)
* Great serialization support (kotlinx.serialization)
* Pragmatic macro-like capabilities via inline functions and compiler plugins (removes lots of boilerplate)
* Multiplatform support (JVM/JS/WASM/native; Graal native image is a good alternative to Kotlin/native and also works for Java)
Although I'm glad to see that Java is still improving, it will never get close to Kotlin. The most obvious reason is that many of Java's early design decisions were revised in Kotlin but are impossible or impractical to revise in Java. Also, Java carries the burden of being a platform language, whereas Kotlin can focus on being the best possible application language.
These days, I only use Java for libraries intended to be used from languages other than just Kotlin. In that case, I don't want to force Kotlin on users (stdlib dependency, debugging, etc.).
One of the big benefits of Kotlin is that if you know Java, you pretty much already know Kotlin, too. A good Java dev can get spun up on the basics in a day or two.
> Both Scala and Kotlin are sufficiently similiar to Java to provide no real benefit.
Kotlin provides a ton of ergonomic features that I absolutely adore. Named parameters and default parameter values alone save me tens or hundreds of lines of code.
I think of Kotlin as what would happen if a Java developer looked at Javascript and asked "okay, but what if this didn't suck?"
I think you mean "what if we took C# and put it on the JVM"? /s
Honestly, C# has had most of the features Kotlin "adds on" to Java for years, even decades.
Sorry but "no real benefit" seems to come from a position of ignorance.
I can only talk about Scala which I know pretty well.
While Clojure is a radical departure from Java, being a Lisp, Scala is a departure thanks to its type system and features that help you writing more functional (as in functional programming) code. And I mean this in a good way: it helps you avoid mutations and side-effects, while giving you the freedom to use good old OOP if you wish so. In general it provides tools that help you better express your intent that Java doesn't have.
I think that Java has too much baggage to ever become as good as Scala, especially on the type system side, and, in addition, Scala is also moving forward.
Also don't forget Scala.js [1], which is rock-solid and just plain amazing, and Scala Native [2].
I'd be sooo happy if that were the case, but sadly, it's not. From the point of view of Scala, I still see many features missing. Roughly in the order of importance:
* Immutable persistent collections in the standard library (and thus lingua franca in the libraries). Just so much better than mutable collections. Way less headache. Once you start using them, you realize how rarely you actually need mutable ones.
* Pattern matching. Java will surely improve on what is currently available. But why wait? It may take a long time.
* Sophisticated string interpolation. It's powerful, and yet is still easy to read. Again, Java is on its way to get it, but with Scala you can have it right now.
* Type Classes. Sometimes it is very good design to separate data from functionality. Java designers (Brian Goetz IIRC) mention they would like to get this eventually. Scala has an interesting design of Type Classes -- "givens" -- which is also modular (in contrast to Haskell). Scala also has an elegant mechanism for Type Class derivation using the "derives" clause. https://docs.scala-lang.org/scala3/reference/contextual/deri...
* for-comprehension syntax and IO/Task/ZIO for async programming. Project Loom still hasn't delivered. But Scala has you covered. It gives you for-comprehension syntax, so that you don't have to suffer from nested callback hell. And there are many great libraries for async programming, like ZIO or Cats Effect. These are easier to work with, compared to other Futures from various Java libraries, because they're lazy, not eager. for-comprehension syntax is also useful for other things, it's just that async is the typical usecase.
Higher-kinded types. Not everything has to be super fancy higher-kinded type-level craziness. And very often one gets away without needing to use higher-kinded types and that's good (just as often a solution without parametric polymorphism aka generics is enough). But other times it's awesome to have this power of abstractions. Typically, but not only in libraries.
* Object. Sometimes you just need to have an object (which might implement an interface/class/trait). But Scala doesn't force you to create a whole class, if you only even want just one instance anyway. A small thing, but way more elegant.
But I'm really happy to see Java/JVM improve. The 17 release has brought some great features, but in the language level (records, embryonic pattern-matching, ...) and the VM level (GCs in particular). We all benefit more or less directly, one way or the other.
All in all, I do find using Scala can absolutely worth it, but I really don’t feel it with Kotlin. It feels like a watered down Scala, and add to that where modern Java currently is, I feel it is not needed.
I guess you could try to argue mobile is bad or something, but you get Kotlin not JDK on mobile.
Yes, Clojure is probably better, but on the flip side as a developer knowing Java 8 and Kotlin is better than knowing Clojure and JDK 17. Perhaps you can point to some salaries here but Java developers are not in short supply, if you wanted to play that game there are better languages for more lucrative payout (assuming you can even get them, these tend to be boutique shops not generally hiring publicly)
However they will most likely assign an intern to port it to Kotlin than improve Java's support on Android.
IMO if you're serious about using the JVM you should be using Java 17 and following the latest version. Kotlin is usable, but it doesn't bring that much more to that table other than longer compile times.
Or at least the perf advantages it brings. Java has nice stuff today maybe but one could argue that it is primarily defending market share that caused Oracle to move forward with its language updates.
I'm inclined to say the opposite, the more the JVM stays healthy and the stronger the third party ecosystem the more likely it doesn't become a 'dead' language like COBOL or FORTAN (not dead but in terms of marketshare).
I only ask because I've never gotten a straight answer with an actual number.
SPSS comes to mind too.
https://developer.apple.com/library/archive/navigation/index...
It absolutely is.
Java isn't sexy, for the most part. It lets a lot of innovation happen in other languages, then takes the successful parts for itself. This is how we (eventually) got generics, lambdas, streams, and local type inference, for example.
Java slowly becomes more ergonomic, and that slowness - the slowness to change, not execution speed - is why it gets a lot of hate. Why use Java, when $LANGUAGE_OF_THE_DAY has $FEATURE_OF_THE_DAY?
What people fail to realize, what people fail to see the value of, is that this slowness means Java doesn't get worse. Java has avoided most unforced errors. It's not like C++, where the template language is both Turing complete and the fastest way to summon Beelzebub from the depths of his infernal pit, and where you need a team of PhDs to decide which version of `auto_pointer` actually works the way you think it does. It's not Javascript, where the framework your front-end lead sold you on last week has already been superseded by the hot new thing.
And you don't generally have to worry about compatibility. Until v9, you could take code written against the 1.0 spec of the language and expect it to run pretty much out of the box. And the changes post v9 honestly aren't that difficult to work through, as opposed to Python's 2 -> 3 split.
Java isn't the sexiest language out there, but it hits a very sweet spot, right in the middle of the "familiar", "stable", and "productive" Venn diagram. It's probably the second-most important computer language developed in my lifetime, after Javascript, and is without a doubt a smashing success story.