khachik khachik - 6 months ago 34
Java Question

Java conditional compilation: how to prevent code chunks from being compiled?

My project requires Java 1.6 for compilation and running. Now I have a requirement to make it working with Java 1.5 (from the marketing side). I want to replace method body (return type and arguments remain the same) to make it compiling with Java 1.5 without errors.

Details: I have an utility class called

OS
which encapsulates all OS-specific things. It has a method

public static void openFile(java.io.File file) throws java.io.IOException {
// open the file using java.awt.Desktop
...
}


to open files like with double-click (
start
Windows command or
open
Mac OS X command equivalent). Since it cannot be compiled with Java 1.5, I want to exclude it during compilation and replace by another method which calls
run32dll
for Windows or
open
for Mac OS X using
Runtime.exec
.

Question: How can I do that? Can annotations help here?

Note: I use ant, and I can make two java files
OS4J5.java
and
OS4J6.java
which will contain the
OS
class with the desired code for Java 1.5 and 1.6 and copy one of them to
OS.java
before compiling (or an ugly way - replace the content of
OS.java
conditionally depending on java version) but I don't want to do that, if there is another way.

Elaborating more: in C I could use
ifdef, ifndef
, in Python there is no compilation and I could check a feature using
hasattr
or something else, in Common Lisp I could use
#+feature
. Is there something similar for Java?

Found this post but it doesn't seem to be helpful.

Any help is greatly appreciated. kh.

Answer

Nope there isn't any support for conditional compilation in Java.

The usual plan is to hide the OS specific bits of your app behind an Interface and then detect the OS type at runtime and load the implementation using Class.forName(String).

In your case there no reason why you can't compile the both OS* (and infact your whole app) using Java 1.6 with -source 1.5 -target 1.5 then in a the factory method for getting hold of OS classes (which would now be an interface) detect that java.awt.Desktop class is available and load the correct version.

Something like:

 public interface OS {
     void openFile(java.io.File file) throws java.io.IOException;
 }

 public class OSFactory {
     public static OS create(){
         try{
             Class.forName("java.awt.Desktop");
             return new OSJ6();
         }catch(Exception e){
             //fall back
             return new OSJ5();
         }
     }
 }