title |
---|
Just enough Java for Crafting Interpreters |
I've been working my way through Robert Nystrom's Crafting Interpreters and had to learn some Java in order to run
the Scanner
class implemented in Chapter 4.
The last time I wrote Java was right before I withdrew from my first CS 101 course, so I had to put some time into mastering the basics. This post documents a handful of the things I had to learn to start scanning tokens in Lox!
Here's a link to an example that will have you up and running with Java in no time! https://github.com/jshawl/just-enough-java-for-crafting-interpreters
The last time I tried installing the JDK on a mac, I was prompted to create
an account with Oracle, which I did not want to do. I decided to go with
docker compose
for all of my Java work. The compose.yml
file looks like:
services:
java:
image: eclipse-temurin:17
Starting the java
service with docker compose run java bash
will open
a shell where you can then run javac
to compile your code and java
to
run it.
I created my first class inside of com/jshawl/example
so that the package
name com.jshawl.example
matched the directory structure. More on packages
in a minute...
Your directory structure should look like this:
./
├── com/
│ └── jshawl/
│ └── example/
│ └── FirstClass.java
└── compose.yml
and inside of FirstClass.java
:
package com.jshawl.example;
class FirstClass {
public static void main(String[] args) {
System.out.println("Hello from FirstClass!");
}
}
Let's modify the compose.yml
to specify a volume for the newly
created com/
directory:
services:
java:
image: eclipse-temurin:17
+ working_dir: /app
+ volumes:
+ - ./com:/app/com
Start the container:
docker compose run java bash
Compile the code:
javac com/jshawl/example/FirstClass.java
This will create a new file com/jshawl/example/FirstClass.class
.
You can now run this code with:
java com.jshawl.example.FirstClass
#=> Hello from FirstClass!
Packages allow us to group related classes and use a namespace to import
classes from the standard library à la import java.io.BufferedReader
.
For the examples in Crafting Interpreters, several classes reference
each other, and a shared package allows us to include code without a
specific import
statement.
Let's create a second class to demo this functionality:
// in com/jshawl/example/SecondClass.java
package com.jshawl.example;
class SecondClass {
public static void greetings() {
System.out.println("Greetings from SecondClass.");
}
}
and create an instance of this class inside of FirstClass.java
:
public static void main(String[] args) {
System.out.println("Hello from FirstClass!");
+ SecondClass secondClass = new SecondClass();
+ secondClass.greetings();
you can now recompile:
javac com/jshawl/example/FirstClass.java
and run and you'll see the output from SecondClass
:
java com.jshawl.example.FirstClass
#=> Hello from FirstClass!
#=> Greetings from SecondClass.
You might have noticed I didn't explicitly compile SecondClass
. javac
is smart enough to compile the code that is referenced in FirstClass
.
If you wanted to compile everything even if it isn't used anywhere yet, use a glob:
javac com/jshawl/example/*.java
I'll plan to come back and add to this guide if I encounter any other foundational knowledge about building and running Java programs, but so far this was enough for me to start a jlox prompt.
Happy hacking!