I like that this illustrates the C#/Java enterprise programming-ism that all identifiers must be in completely random namespaces to make it look fancier.
Is it helping anyone that the print function is under Console? Why is an array a standard type but also a class named ArrayList under System.Collections?
(Which seems to be deprecated and replaced with a class called List that's now under three namespaces instead of two.)
but what is the better alternative (if any) though? In practice this can help to enable having the same Square class name, just one in MyPackage and another in SomeOtherVendorPackage.
This is a preview feature that still requires the --enable-preview flag. It's meant to reduce the initial cognitive load when teaching programming rather than an embrace of terse syntax.
Which would have zero benefits, and would require more knowledge on the exact specifics of the language. (Eg. is it a local variable of a field? The two has very different semantics).
I assumed they were just making any method called 'main' sugar for public static void.
But it's not that way. Instead, apparently the proposal is to allow for main to be an instance method.
Additionally, we are getting anonymous classes.
Because methods can share names (both between inheritance and with different args) we apparently get a warning if a superclass also has a static main being overridden with an instance main. I would have preferred if this was simply an error.
> the proposal is to allow for main to be an instance method
An instance method of... which instance? Is some invisible, nameless class instantiated with its default constructor? How would you acquire this main method via reflection?
Imagine `public class [randomName] {` at the top. If it has a void main() method the class loader (not the spec!) will do new [randomName].main()
You won’t acquire this main via reflection because why would you do so? It is for teaching, and one-off scripts. Later on you can trivially add that single line and name your class.
With all the hype about "modern" Java I still have escape regex metacharacters even after the introduction of raw string literals. Wake me up if/when Java finally fixes what really needs fixing.
I’m not a fan of this personally. It seems very pedantic and honestly the IDE gives such great hints on things already —- I don’t think it actually helps anyone learn anything in the long run.
Also worth mentioning is that having multiple ways to do the same thing also increases complexity
But that’s the thing, they managed to do it in such a way that it requires barely any language change: just imagine an implicit `public class X {` at the top of the file and a closing } at the end.
And now just change the default class loader to be less restrictive in finding main methods, and that’s it. While it really does help teaching people when you can be more focused on the relevant parts only.
> the IDE gives such great hints on things already
Requirement to use IDE is one of reasons I don't like Java. I wrote/write code in multiple languages and for all of them a simple text editor is enough. I usually don't use auto-complete because it distracts me and I type fast anyway. But with Java it's hard to be productive without an IDE.
I will never understand why some people actively choose to cripple their productivity. Is it some irrational pride in being able to drill without power tools?
Languages and IDE come and go, vim remains. It is enough to learn it once (so common things are done without additional thinking) and use for different languages. It is also one of very few editors available for all desktop and server OSes I used over the time. I tried to use IDE and Java is the only case where my productivity was crippled without it (C# probably would be the same but I haven't used it). I don't deny IDE have lots of useful features. I just don't feel I need them.
You could make the same argument for using console logging instead of debuggers, and many developers get along with that just fine. Yet they’re missing out on a lot of productivity they never knew was able to be gained.
Debug logs and debugger not replace but complement each other. And while in many situations it is possible to debug without a debugger by adding print-s reverse is not true - I see no way how a debugger can replace logs. Though good debug logs are rare nginx and postfix are rare examples where debug logs are really useful (may be bad debug logs is why this tool got bad reputation).
What to some extend can replace debug logs is tracing which allows to logs events on demand, when you really need them. E. g. Dtrace can be used both for kernel and userspace via USDT (but Dtrace was not invented h̵e̵r̵e̵ on Linux), bpftrace can instrument kernel but unsure about userspace.
vim mode definitely helps, but still it is not the same as using vim directly. My vimrc is small compare to what I see people share but still has 180 non-comment lines, the same with plugins - only a few but I really use them.
For me, using an IDE would be “crippling my productivity”. Instead of just starting to code, I'd have to wait a few minutes for the IDE to open, and click through a billion GUI windows, just to be able to see my code in a tiny window surrounded by dozens of useless toolbars. And whenever I try to do anything with the code, it will take a second to process my keystroke and then several windows will pop up, obscuring half of the tiny part of the screen that actually contains code. And as a bonus, I'd have to pay more money for this than my dormitory costs? No thanks, I'll stick with Neovim.
Getting better equipment (larger screens, faster computers, licences) would solve most of your concerns with the IDEs. And getting better equipment usually soon becomes a non-problem for professional programmers.
Having an IDE is like hiring a side-kick --- if the side-kick is component enough and you can afford them, why wouldn't you hire one?
... and IDEA community edition is also free. There's no reason to not choose any of the major IDEs on the basis of cost. You can get free and quite workable editions of all of them, and they're open source as well, so the "moral quandary" is avoidable unless it's artificial.
What's your definition of "proprietary?" All of the major IDEs are open-source in their free editions.
I mean, more seriously, I get it: you have a bee in your bonnet and you will find any reason possible to avoid it. VIM 4EVA and all that, raise your fist and yell.
But I wouldn't even bother with Java as any serious endeavor if I were you; a lot of employers will ask your preference of IDE just to get a sense of who you are as a programmer, and will hide their giggles when you say "I use emacs/vim/notepad++ like a BAWSSSS!" and move on to the next candidate who'll get the performance magnifier of a common and free tool.
What a strawman. I don't use Neovim with the intent of looking cool or something, but because it makes me highly productive, gives me complete control over my editing experience and I can use it anywhere, not just on powerful desktop computers with a large screen.
You actually wouldn't. You might once - but then you're counting "installing the IDE" as "using the IDE every time" and that just doesn't happen. You're also using a LOT of hyperbole, to the point where you're just plain wrong.
A few minutes for the IDE to open? Nah, bruh. Couple of seconds, and since you leave the IDE open for a while, that startup time gets to be ignored. You aren't starting the IDE, exiting the IDE, running your code, starting your IDE, exiting the IDE, running your code.
You're starting the IDE, writing, running, debugging, reaching some kind of finishing point, THEN shutting down the IDE... maybe. A lot of programmers have their IDEs open 24/7. Over a month's runtime, those three seconds opening the IDE seem (and are) irrelevant.
Billion GUI windows? Nah, bruh. Even IDEA, which has a lot of windows on initial installation, has only a few... and they're all for a point, if you, like, read them.
A second to process your keystroke? Also nonsense. Even a raspi can process faster than that. Unless you're deliberately overloading your machine, I suppose. That's always an option... but a counter to that is "... don't?"
And useless toolbars? Useless to whom? The IDEs you'll find in Java are battle-tested. The useless toolbars are hidden these days. You might not know what they're useful for, but that's not the same as being useless. If you write Java, you'll learn how useful they are.
And as a bonus, you'd ... did you say.. have to pay more money than your dorm costs? ... why?
Java has three major IDEs: IDEA, Eclipse, and Netbeans. (If you want to exclude netbeans, join the crowd. Everyone else excludes it, too.) All three have free editions that cost you ... like... literally... nothing. Zip. Nada. Zilch.
I was skeptical too. But after reading the JEP i think i am convinced.
It makes an analogy to packages. We allow classes to exist in the default package. Therefore, I think it's reasonable to allow methods to exist in a default class.
Of course you shouldn't so this in real work, but that's also true of the default package.
I also like that main doesn't need an argument. Many noob programs don't even use the String[] args parameter anyway, so let's not require it.
Same here. `psvm` is perfectly consistent with the rest of the language. IMHO it is much better to have a consistently verbose/explicit language than an inconsistent one.
I personally like using IDEs when coding. Reading is another matter, and the code we read will not always be inside an IDE (e.g. code shared on the web, or written in a book).
When teaching Java a while ago, "public static void main string args" was a great way of teaching many things about programming and the Java language right off the bat.
I actually liked how the cmdline args were always immediately available in the main method, unlike other languages like Python where you need to load a whole separate module to access them.
As do all students at my university where Java is not only the first language, but also used for Data structures and Algorithms, practical semester projects, etc. Many of these people finish their degrees without knowing languages other than Java and maybe Python and C/C++ exist.
I don't think it's a bad beginner language at all. It's low level enough to learn about the inner workings in a structured way, but it's high level enough to not run into segmentation errors all the time. In some courses they wrote Java bytecode as a substitute for an assembly language, which seems completely sensible to me since it'll be more broadly applicable than a specific ISA.
Setting up the tooling was a pain though. I did the JavaFX parts of the exam without ever having used it because I (with the help of multiple Linux nerds!) couldn't get it to run on Arch.
When was it? JavaFX is not completely painless, but chances are you only need a single package available by default on most distros, if anything nowadays.
(Some distros may even package a JDK with bundled javafx).
Here are some other features to make Java more modern:
- Replace `System.out.println` with just `println`
- Add operator overloading and subscript overloading for lists and maps
- Add string templates with `$`, e.g. `"Hello ${user.name}!"`
- Add range types, e.g. `for (i in 1..10) { ... }`
- `val` keyword, like `var` but only doesn't let you assign to the variable after defining it
- Add coroutines
- Make `==` use `equals`, and define `===` for identity comparison
- Make types non-nullable by default, and use `?` to denote nullable types. Use `!` to cast a nullable type to non-nullable, and `?.` to access a field on a potentially nullable object
- Add readonly types for arrays and maps: replace `List` with `List` and `MutableList`, and `HashMap` with `Map` and `MutableMap`.
- Get rid of sigils for array types, use `Array` instead. Also get rid of lowercase and uppercase variants for primitive types, just use the uppercase ones for consistency
- Make it so that when a lambda is the last argument it can be outside of parentheses, when it's the only argument parentheses aren't needed, and when it has no arguments you can omit the `() =>`
- Put type annotations after the variable like in most modern languages, and use the `fun` keyword for functions. So instead of `void main(String[] args)` you would write `fun main(args: Array<String>)
- Put class constructor parameters on the class declaration, and allow them to be fields by specifying `var` or `val`, like `class Rectangle(var width: Double, var length: Double) {}`
- `init` blocks in classes for initialization code, and `constructor(sideLength: Double) : this(sideLength, sideLength)` for alternate constructors
- Add the `when` condition as a better replacement for `if else` chains.
- Add convenience functions to all objects: `x.let(fun)`, `x.also(fun)`, `x.apply(fun)`, `x.use(fun)`, and `x.apply(fun)`
I'm sure there are more improvements I haven't mentioned, but these would all be good first steps to make Java almost as good as other JVM languages like Kotlin
The first few points seem like good first steps but you soon got to a land of "never gonna happen" and then you finally just landed on kotlin itself. Why not just use Kotlin?
String templates are coming, there is IntStream.range(1, 10), there is `final var`, I don’t see much point to having coroutines with Loom, == would be ecosystem fracturing breaking change so please no, that nullability might actually come with the recent direction Valhalla’s value types took, readonly collections would be cool, but that ship has sailed, array sigils are such a small thing I don’t see the benefit, I don’t get the lambda one, variable: Type is again a breaking change for not good enough reason, records are immutable but once withers complete they will be imo better, you do have static blocks but with records you also get a canonical one with very similar syntax than what you want, if expressions were actually great, nested ternaries are the only syntax I really have a hard time with even after many years.
Kotlin is not the panacea of language design either.
Kotlin is hardly a nobody language (being the default language for Android development these days). That being said, a lot of these are no-gos from a backwards compatibility perspective, and if you want them, I'm not sure why you wouldn't just use Kotlin.
Came here to say exactly this. The language you are describing already exists. HN seems hellbent on pretending it hasn’t changed in 10 years but Dart was very much designed from the POV of what if we took the good parts from both Java and JS and left the bad bits behind and compiled it to native machine code. It’s actually a really good outcome that’s incredibly underrated.
My main gripe with Dart is their package manager. Unlike NPM or Cargo, it is possible to get conflicting diamond dependencies. The lack of shared memory concurrency is also disappointing.
You forgot about backwards compatibility, which is very high on the Java features priority list. Things like "Make `==` use `equals`" will NEVER happen in Java.
Many of you other points are also purely stylistic (eg. types before or after parameter/variable names), these will not change just because you don't like it.
There's a single other kind of concurrency: unstructured concurrency. Which is where you just start threads/goroutines/coroutines/etc and they just... all do their own little thing ? They can return at any time, have no parents, etc.
Structured concurrency is about making a tree of concurrent processes. You may have a parent job, that has children. Cancelling this job will cancel all its children. For example, you may have a job that's linked to an UI (so it needs to stop the moment that UI is gone), to a socket (so it needs to stop the moment the socket closes), or to nothing and is a global scope (that will keep running as long as your OS doesn't exit the process). These scopes can in turn have their own children and their own scopes. And maybe you have a task way, way down in your tree that spawns two tasks: one is a long running task that must exit the moment its parent stops ("the user clicked on cancel"), one is a long running task that must stay alive as long as necessary ("the user's data is being uploaded to a server in the background"). With unstructured concurrency, you can't really express that. With structured concurrency, just pass the appropriate scope down.
I'd vote no on most of these for Java language itself; it's supposed to be a C-like language, not a Ruby-like language. However, the jvm doesn't care what the source language is, it just cares about bytecode. These belong in a Kotlin or other language.
A lot of these are no-gos anyway from a backwards compatibility perspective (many of which being entirely syntactical), and they're already in Kotlin, so I'm not sure why you wouldn't just use that. A couple I could potentially see making their way into Java though.
Exactly my thoughts. Let Java be Java. It's not that I disagree with most of them I just don't think it needs to have every bell, whistle, and doodad either. Simplicity is beauty.
I very much like the idea of Java. A runtime for everything! Wow!
But it feels like the coolest aspects of this idea have been
realized more by .NET than by Java itself. Powershell, for instance, is so cool (in theory) because it lets you dynamically mess around with and script statically compiled components. This could (in practice it's not, since I haven't found good tooling) be so great for debugging.
I've found that it works better to use a 'real' programming language for scripts and use a UNIX shell for interactive REPL-like use. The syntax of the command line is hard to beat one you master it because it's so terse and for one-to-ten line programs like you get in a REPL maintainability doesn't matter. For anything else, it's better to write a script file and execute it. The tradeoffs are different and what works well for a program meant to stick around doesn't work well interactively. The downside of course is that if you perfect a bit of logic with a repl, you then have to translate to the other language.
My company uses an in-house variant of Kotlin Scripting which has replaced bash and python for us. It's got a lot of neat features, like you can echo markdown to the terminal and it'll be rendered nicely, it has a built in progress tracking framework, it has a UNIX-like shell API for working with files and processes, you can import libraries from Maven and use them directly and so on.
The only real downsides are that it's slow to compile, and currently Kotlin Scripting is still in a (very long) beta period. Hopefully when they finally release version 2 of the compiler it'll be faster and they can finally nail down the scripting support a bit better.
But I have to say, it's really enjoyable to use. I used to dread shell scripting tasks because shell is just so persnickety. Now I don't. Java has something similar with jbang and jshell, but the Java syntax is perhaps a bit too verbose still. They're improving it a lot though!
I don't think this is "bad", but every single person this appeals to has already switched to a different JVM language or C#.
It's also somewhat of a break with tradition for Java and it's clear OOP inheritance.
81 comments
[ 3.8 ms ] story [ 106 ms ] threadConsole.WriteLine(“Hello, World!”);
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tu...
Is it helping anyone that the print function is under Console? Why is an array a standard type but also a class named ArrayList under System.Collections?
(Which seems to be deprecated and replaced with a class called List that's now under three namespaces instead of two.)
This is a preview feature that still requires the --enable-preview flag. It's meant to reduce the initial cognitive load when teaching programming rather than an embrace of terse syntax.
I assumed they were just making any method called 'main' sugar for public static void.
But it's not that way. Instead, apparently the proposal is to allow for main to be an instance method.
Additionally, we are getting anonymous classes.
Because methods can share names (both between inheritance and with different args) we apparently get a warning if a superclass also has a static main being overridden with an instance main. I would have preferred if this was simply an error.
An instance method of... which instance? Is some invisible, nameless class instantiated with its default constructor? How would you acquire this main method via reflection?
You won’t acquire this main via reflection because why would you do so? It is for teaching, and one-off scripts. Later on you can trivially add that single line and name your class.
Also worth mentioning is that having multiple ways to do the same thing also increases complexity
It's for beginners who might not even know what an IDE is.
And now just change the default class loader to be less restrictive in finding main methods, and that’s it. While it really does help teaching people when you can be more focused on the relevant parts only.
Requirement to use IDE is one of reasons I don't like Java. I wrote/write code in multiple languages and for all of them a simple text editor is enough. I usually don't use auto-complete because it distracts me and I type fast anyway. But with Java it's hard to be productive without an IDE.
What to some extend can replace debug logs is tracing which allows to logs events on demand, when you really need them. E. g. Dtrace can be used both for kernel and userspace via USDT (but Dtrace was not invented h̵e̵r̵e̵ on Linux), bpftrace can instrument kernel but unsure about userspace.
Having an IDE is like hiring a side-kick --- if the side-kick is component enough and you can afford them, why wouldn't you hire one?
> if the side-kick is component enough and you can afford them, why wouldn't you hire one?
Because it doesn't provide anything actually useful for me.
Also, I don't want to use proprietary software for moral reasons.
There are many decent open source IDEs (e.g. NetBeans and Eclipse for Java).
I mean, more seriously, I get it: you have a bee in your bonnet and you will find any reason possible to avoid it. VIM 4EVA and all that, raise your fist and yell.
But I wouldn't even bother with Java as any serious endeavor if I were you; a lot of employers will ask your preference of IDE just to get a sense of who you are as a programmer, and will hide their giggles when you say "I use emacs/vim/notepad++ like a BAWSSSS!" and move on to the next candidate who'll get the performance magnifier of a common and free tool.
What a strawman. I don't use Neovim with the intent of looking cool or something, but because it makes me highly productive, gives me complete control over my editing experience and I can use it anywhere, not just on powerful desktop computers with a large screen.
A few minutes for the IDE to open? Nah, bruh. Couple of seconds, and since you leave the IDE open for a while, that startup time gets to be ignored. You aren't starting the IDE, exiting the IDE, running your code, starting your IDE, exiting the IDE, running your code.
You're starting the IDE, writing, running, debugging, reaching some kind of finishing point, THEN shutting down the IDE... maybe. A lot of programmers have their IDEs open 24/7. Over a month's runtime, those three seconds opening the IDE seem (and are) irrelevant.
Billion GUI windows? Nah, bruh. Even IDEA, which has a lot of windows on initial installation, has only a few... and they're all for a point, if you, like, read them.
A second to process your keystroke? Also nonsense. Even a raspi can process faster than that. Unless you're deliberately overloading your machine, I suppose. That's always an option... but a counter to that is "... don't?"
And useless toolbars? Useless to whom? The IDEs you'll find in Java are battle-tested. The useless toolbars are hidden these days. You might not know what they're useful for, but that's not the same as being useless. If you write Java, you'll learn how useful they are.
And as a bonus, you'd ... did you say.. have to pay more money than your dorm costs? ... why?
Java has three major IDEs: IDEA, Eclipse, and Netbeans. (If you want to exclude netbeans, join the crowd. Everyone else excludes it, too.) All three have free editions that cost you ... like... literally... nothing. Zip. Nada. Zilch.
Try again.
You can take vim out of my cold dead hands but there’s no way one will be less productive in Java with modern IDEs unless they willingly choose to
Exactly.
It makes an analogy to packages. We allow classes to exist in the default package. Therefore, I think it's reasonable to allow methods to exist in a default class.
Of course you shouldn't so this in real work, but that's also true of the default package.
I also like that main doesn't need an argument. Many noob programs don't even use the String[] args parameter anyway, so let's not require it.
I actually liked how the cmdline args were always immediately available in the main method, unlike other languages like Python where you need to load a whole separate module to access them.
When I learned Java as a first language, I remember being very confused by those words. They did not make sense to me for months.
To a noob, it's a meaningless incantation that needs to be inserted for each project.
You have my sympathies
Setting up the tooling was a pain though. I did the JavaFX parts of the exam without ever having used it because I (with the help of multiple Linux nerds!) couldn't get it to run on Arch.
(Some distros may even package a JDK with bundled javafx).
I have been on the same path.
- Replace `System.out.println` with just `println`
- Add operator overloading and subscript overloading for lists and maps
- Add string templates with `$`, e.g. `"Hello ${user.name}!"`
- Add range types, e.g. `for (i in 1..10) { ... }`
- `val` keyword, like `var` but only doesn't let you assign to the variable after defining it
- Add coroutines
- Make `==` use `equals`, and define `===` for identity comparison
- Make types non-nullable by default, and use `?` to denote nullable types. Use `!` to cast a nullable type to non-nullable, and `?.` to access a field on a potentially nullable object
- Add readonly types for arrays and maps: replace `List` with `List` and `MutableList`, and `HashMap` with `Map` and `MutableMap`.
- Get rid of sigils for array types, use `Array` instead. Also get rid of lowercase and uppercase variants for primitive types, just use the uppercase ones for consistency
- Make it so that when a lambda is the last argument it can be outside of parentheses, when it's the only argument parentheses aren't needed, and when it has no arguments you can omit the `() =>`
- Put type annotations after the variable like in most modern languages, and use the `fun` keyword for functions. So instead of `void main(String[] args)` you would write `fun main(args: Array<String>)
- Put class constructor parameters on the class declaration, and allow them to be fields by specifying `var` or `val`, like `class Rectangle(var width: Double, var length: Double) {}`
- `init` blocks in classes for initialization code, and `constructor(sideLength: Double) : this(sideLength, sideLength)` for alternate constructors
- Add the `when` condition as a better replacement for `if else` chains.
- Add convenience functions to all objects: `x.let(fun)`, `x.also(fun)`, `x.apply(fun)`, `x.use(fun)`, and `x.apply(fun)`
I'm sure there are more improvements I haven't mentioned, but these would all be good first steps to make Java almost as good as other JVM languages like Kotlin
Kotlin is not the panacea of language design either.
Your suggestions are basically all just meme features from nobody languages. Java is the king for a reason.
Of all the reasons Java is popular, ergonomics is absolutely not one of them.
Many of you other points are also purely stylistic (eg. types before or after parameter/variable names), these will not change just because you don't like it.
There's a single other kind of concurrency: unstructured concurrency. Which is where you just start threads/goroutines/coroutines/etc and they just... all do their own little thing ? They can return at any time, have no parents, etc.
Structured concurrency is about making a tree of concurrent processes. You may have a parent job, that has children. Cancelling this job will cancel all its children. For example, you may have a job that's linked to an UI (so it needs to stop the moment that UI is gone), to a socket (so it needs to stop the moment the socket closes), or to nothing and is a global scope (that will keep running as long as your OS doesn't exit the process). These scopes can in turn have their own children and their own scopes. And maybe you have a task way, way down in your tree that spawns two tasks: one is a long running task that must exit the moment its parent stops ("the user clicked on cancel"), one is a long running task that must stay alive as long as necessary ("the user's data is being uploaded to a server in the background"). With unstructured concurrency, you can't really express that. With structured concurrency, just pass the appropriate scope down.
[0]: https://kotlinlang.org/docs/scope-functions.html
What about constants?
But it feels like the coolest aspects of this idea have been realized more by .NET than by Java itself. Powershell, for instance, is so cool (in theory) because it lets you dynamically mess around with and script statically compiled components. This could (in practice it's not, since I haven't found good tooling) be so great for debugging.
My company uses an in-house variant of Kotlin Scripting which has replaced bash and python for us. It's got a lot of neat features, like you can echo markdown to the terminal and it'll be rendered nicely, it has a built in progress tracking framework, it has a UNIX-like shell API for working with files and processes, you can import libraries from Maven and use them directly and so on.
The only real downsides are that it's slow to compile, and currently Kotlin Scripting is still in a (very long) beta period. Hopefully when they finally release version 2 of the compiler it'll be faster and they can finally nail down the scripting support a bit better.
But I have to say, it's really enjoyable to use. I used to dread shell scripting tasks because shell is just so persnickety. Now I don't. Java has something similar with jbang and jshell, but the Java syntax is perhaps a bit too verbose still. They're improving it a lot though!