I’m a huge fan of C# and how Microsoft has been improving .NET recently but as a C# fan I think you’re being a little unfair to Java. It has a slightly different perspective on language evolution than C#, in that they try to keep the language core smaller. I was overwhelmed by syntax when I first started programming C#, from all the different kinds of parameters (optional, named, ref, out, in) to all the different kinds of properties, to the actual difference between properties and fields. To this day I think it’s silly that certain tools and style guides will suggest you replace public fields with public auto-properties, when there is no difference in encapsulation in practice. In this sense C# is closer to the culture of C++, where the bar for adding features is quite low.
Java just moves a lot slower, and has a different philosophy for adding features, and the core team seems averse to introducing new forms. An example I ran into the other day is applying first-class functions in Java: in C#, this looks like
lambda(arg1, arg2)
while in Java it’s
lambda.apply(arg1, arg2)
This is definitely more verbose and arguably uglier, but it hews closer to the object-oriented style because it’s visibly falling a method on an object. Of course this is happening in C# as well, but it’s hidden by syntactic sugar.
> This is definitely more verbose and arguably uglier, but it hews closer to the object-oriented style because it’s visibly falling a method on an object. Of course this is happening in C# as well, but it’s hidden by syntactic sugar.
It's hard to appreciate how addictive the sugar is if you never had it.
Frankly, language level auto properties -alone- would get rid of 25-33% of the pain I feel writing Java.
Of course, there is always Scala on the JVM Side; which gives you all sorts of sugar, but in some ways -too much-.
I think from an object-oriented design perspective that it's quite easy to overuse public field members and that a lot of getters and setters is generally a code smell. Nonetheless, properties are a very sharp tool and having them in the toolkit is wonderful.
I've never used Scala but it seems to go much further in the syntactic sugar and semantic complexity direction, more akin to F# than C# (though with less elegant syntax, to my eye).
There have been many iterations of 'Java except it doesn't suck', but which all were extremely similar to Java - Xtend, Groovy, etc. So when Scala came onto the scene, even though it was a serious functional language and encouraged a very different style of programming than Java, it was seized on as a 'Java except it doesn't suck' language because it was much more different than previous ones and so felt more like a fresh start. The sentiment hasn't died yet, although Kotlin should at this point be treated as the official 'Java except it doesn't suck' language, since it's designed directly for it, is different enough, and has mainstream adoption.
However bad the Java situation is, Lombok as a solution is worse. It uses unsupported and undocumented APIs of the compiler, it autogenerates code that is in some cases flat wrong (like the infamous enum @ToString), and it does this through a mechanism of the language specifically designed for pure metadata - code that compiles with annotations should not cease compiling without them. And, because of the way it does what it does, IDEs must have explicit Lombok support built into them. It is, effectively, a different language that's a superset of Java; at that point, you may as well actually use a superset of Java like Groovy, and then you don't have tools prone to breaking.
I’m not a huge fan of libraries that use attributes as a hook for code generation in C# either, though thankfully there’s less need for something like Lombok.
I am not saying Java's model of never adding important things is better or worse. I might now say it is worse, but that wasn't the point I was making - I was simply responding to a comment saying Java has added important things, when it hasn't.
Also, auto-properties are binary compatible with computed properties, whereas public fields aren't, and you can use 'ref' on a public field whereas you can't make a ref to a property.
I realize there are differences between fields and auto-props when using certain other features, but from a design perspective, these are identical within an assembly:
public int Foo { get; set; }
public int Bar;
Java has absolutely made important improvements, and there are even more impressive ones on the horizon. In particular you should look at Project Loom, which is Java’s answer to async/await. It’s not finished yet because the design is much more general and novel, and it avoids the “function color” problem that async/await has. It’s inspired in part by Erlang/BEAM’s green threading system.
You might also look at the JDK flight recorder, which is an amazing feature that .NET doesn't have. The Java perspective is adding complexity to the runtime fiest instead of the language.
Java just moves a lot slower, and has a different philosophy for adding features, and the core team seems averse to introducing new forms. An example I ran into the other day is applying first-class functions in Java: in C#, this looks like
while in Java it’s This is definitely more verbose and arguably uglier, but it hews closer to the object-oriented style because it’s visibly falling a method on an object. Of course this is happening in C# as well, but it’s hidden by syntactic sugar.