2024-03-03
Ok I’m not really a Java expert… it’s pretty verbose and fits mostly the same use cases as Python… but I still come across it frequently.
Ironically, I haven’t written a guide to Python, which I know much better; I guess I know enough that I feel like I wouldn’t do it justice to write a short guide.
Anyways Java and its JVM is the default runtime of Clojure, and the “write once, run anywhere” ideal of Java is pretty cool. And as we’ll see, the tooling is good.
Most people don’t think “repl” when they think Java. They think “IDE”. But I don’t like IDEs
and I like repls. Fortunately Java has a good repl built in. It’s called jshell
.
It’s included in Java since version 9 which came out in 2017.
$ jshell
| Welcome to JShell -- Version 21.0.2
| For an introduction type: /help intro
jshell>
Declare variables in java with the type like so:
jshell> int x = 3
x ==> 3
jshell> x + 4
$2 ==> 7
Or let java figure out the type using var
(since Java 10):
jshell> var y = 5
y ==> 5
However var
doesn’t always work.
jshell> var xs = {1, 2, 3}
| Error:
| cannot infer type for local variable xs
| (array initializer needs an explicit target-type)
| var xs = {1, 2, 3};
| ^-----------------^
People tend to not use var
in production code anyways.
The type syntax for arrays is:
jshell> int[] xs = {1, 2, 3}
xs ==> int[3] { 1, 2, 3 }
The classic “hello world” in the jshell is:
jshell> System.out.println("Hello world")
Hello world
That’s verbose!!
Ok now that we know how to print “Hello world”, let’s make a program that does that.
Java is very particular about filenames… we’ll see why in a second.
Let’s add our hello world to a file HelloWorld.java
. We need a semicolon now :(
$ echo 'System.out.println("Hello world");' > HelloWorld.java
But when we try to compile that:
$ javac HelloWorld.java
HelloWorld.java:1: error: class, interface, enum, or record expected
System.out.println("Hello world");
^
1 error
Ok so we update HelloWorld.java
to the classic Java boilerplate:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
Now we can compile it:
$ javac HelloWorld.java
$ ls
HelloWorld.class HelloWorld.java
As we can see, this produces HelloWorld.class
. This is the Java bytecode.
We can run it with java
:
$ java HelloWorld
Hello world
Java has some functional features that have been added over time.
Honestly one of the big selling points of Java is that the old stuff still works; you can write a for loop that looks like this:
jshell> int[] xs = {1, 2, 3}
xs ==> int[3] { 1, 2, 3 }
jshell> for(int i = 0; i < xs.length; i++) {
...> System.out.println(xs[i]);
...> }
1
2
3
Or you can use a foreach
style loop:
jshell> for (int x : xs) {
...> System.out.println(x);
...> }
1
2
3
But my preferred way to go about this is to use functional programming.
Since it was added much after the fact (and Java is big on object-oriented code) this style has some quirks.
In order to call .forEach
which is how to pass a function to work on an element,
we can either convert the array to an ArrayList:
jshell> Arrays.asList(xs)
$12 ==> [[I@1b2c6ec2]
jshell> $12.getClass()
$18 ==> class java.util.Arrays$ArrayList
Or just declare a list from the start:
jshell> var l = List.of(4, 5, 6)
l ==> [4, 5, 6]
Now we can iterate over our list:
jshell> l.forEach(x -> System.out.println(x))
4
5
6
That ->
is the lambda syntax. Cool!
Since we’re just calling a function with a single argument, you’d think we could do:
jshell> l.forEach(System.out.println)
| Error:
| cannot find symbol
| symbol: variable println
| l.forEach(System.out.println)
| ^----------------^
Ok it can’t access println as a function; this is where the object-oriented + functional starts to clash somewhat. I guess it could be akin to the old-style Python print statement as opposed to the Python 3 print function. Java would never do that; it’d break backwards compatibility.
Fortunately they have this syntax for accessing a method as a function:
jshell> l.forEach(System.out::println)
4
5
6
There you have it, functional Java. Had to jump through some hoops but the final result ain’t bad.