Ask a random person on the street if Java has a preprocessor and they’ll probably say “no, that’s a C thing”.

Of course, that doesn’t really make sense. Preprocessing Java would mean modifying Java code before it gets interpreted as Java. That’s totally possible. Java tools just don’t have that functionality built in.

gcc has a built-in preprocessor. How about we use it?

Here’s some Java code with a #if in it. (paste into a file called Hello.java if you want to try this at home).

class Hello {
    public static void main(String[] args) {
#if DEBUG
    System.out.println("About to print 'Hello Internet!'");
#endif
    System.out.println("Hello Internet!");
    }
}

Step 1. Disguise the Java as C.

mv Hello.java Hello.c

Step 2. run the C preprocessor.

gcc -E -P Hello.c -o Hello.java

Step 3. Compile the resulting file as Java.

javac Hello.java

Step 4. Recover the original java.

mv Hello.c Hello.java

Step 5. Run the program.

$ java Hello
Hello Internet!

Now, try it with DEBUG=1

mv Hello.java Hello.c
gcc -E -P -DDEBUG=1 Hello.c -o Hello.java
javac Hello.java
mv Hello.c Hello.java

Run the program again:

$ java Hello
About to print 'Hello Internet!'
Hello Internet!

Behold! the Java preprocessor!

Now, you’re in for some work if you want to use this in your tool-chain. You’ll probably want to take into account the fact that the preprocessor can muck with line numbers and your Java compiler will lie to you about the locations of errors. If you remove -P, gcc will output a file with meta data that you can use to track the origin of an error, but this is starting to get complicated. Making your text-editor color your code right is going to be just about impossible. In short, getting back the comfort you had before would be a hassle.

And probably you don’t want to deal with even a small hassle just to create an arcane tool that will enable you to write .java files no other Java development environment can understand.

But I think I’ve made my point. The C preprocessor is not actually that specific to C. It’s a separable module that can be used all by itself.