We had a good discussion while I was in the informal meetup today, and I'm putting together a summary of action items we might want to consider for outreach (more blog posts, more content on short-form video sites, refreshing old articles and projects). One of the ideas I had that I really want to dig into is that new developers aren't looking for their next "enterprise application" language. They want to run something small, quickly. Java is not known for being small or quick.
I wanted to try playing with the "small" hello world, since it was mentioned that other language fans still use this as a way to dunk on Java.
I believe the smallest we can get right now in 25 (as a readable one-liner without golfing) is:
void main() { IO.println("Hello!"); }This can be run with java hello.java (filename is unimportant) and that's obviously much easier than what we had in the past.
$ java hello.java
Hello!
But this is still a nonstarter for folks trying their first line of code because you have to:
- Know how to declare the main function
- Know that println is a function in IO
- Terminate even one-liners with a semicolon
- Write it to a file
- Run
javaagainst that file
Compare with Ruby (JRuby in this case) which wins by 23 characters and doesn't require most of this (Python would be similar):
$ ruby -e 'puts "Hello!"'
Hello!
Even JRuby using Java APIs and no automatic imports is fewer characters (and no file):
$ jruby -e 'java.lang.IO.println("Hello!")'
Hello!
$ echo 'java.lang.IO.println("Hello!")' | wc -c
31
$ wc -c hello.java
40 hello.java
As I understand it, the proposal to allow command-line script execution to omit main was rejected. I think that's a mistake, but even more than that I think the java command line needs a refresh. I'm playing around with a set of shell functions I call "j":
$ j hello.java
Hello!
$ j -e 'IO.println("Hello!")'
Hello!
The -e argument here strips away most of those requirements:
- With no
-eit runs like normal Java command line - With
-eit creates a temp file containing that code and runs it- Boilerplate for main is injected
- Trailing semicolon is added for one-liners
j()
{
if [ "$1" = "-e" ]; then
javae ${@/-e}
else
java $@
fi
}
javae()
{
tempfile=$(mktemp javaeXXXX.java)
echo "void main() {">$tempfile
echo $1>>$tempfile
echo ";}">>$tempfile
java $tempfile
ret=$?
rm $tempfile
return ret
}So this is just a rough idea and proof-of-concept, but what do other champions think about building a "modern" command line interface for Java that feels a bit more like competing command-line-friendly languages like Python, Ruby, Perl? With all the work on startup time (AppCDS, Leyden, etc) we can be competitive on CLI speed (sub-500ms), but those extra steps really turn people off.
$ time java hello.java
Hello!
java hello.java 0.75s user 0.04s system 230% cpu 0.347 total
Other ideas:
- -I (that's an "i") for adding classpath entries, as in
-I jruby.jar - Allow users to leave .java files uncompiled and compile them on-demand, like Python or Ruby
- Using a language other than shell to implement "j", either something native like zig (clean and simple, https://ziglang.org/) or amber (compiles to shell, https://amber-lang.com/). Maybe even written in Java and native compiled?
- Pre-importing other things we know people will want, like java.util collections
- Piping scripts on stdin
- Additional flags for stdin and file processing niceities like
-nin Ruby (code runs inside a stdin.gets loop)
I think the value of a simple command line for one-liners can't be understated... it's how nearly every dynamic language introduces people to simple concepts (and how I run 90% of my quick Ruby experiments) and it aligns well with jshell's classless UX.
jshell> IO.println("Hello!")
Hello!
For that matter, why doesn't jshell itself include a "-e" that can run what I'd enter at the jshell prompt? jshell -Imy.jar -e'my.java.code()' would go a long way toward getting folks in the door.
Anyway... this is a bit of fun but in all seriousness... Java's command-line story really sucks, and it's the first thing that new developers see. It needs an update.