As a separate answer: The equivalent of conditional compilation in Java.
(It might have been better for you to ask this as a separate question).
As you probably know, Java doesn't really have conditional compilation, certainly not in the sense of C's preprocessor.
For some cases, it's easy enough to put each coding alternative into an if
block controlled by constants, err, static final
fields. If those fields can be evaluated at compile time so their values are effectively constants, then the compiler is smart enough to completely remove code in if
blocks controlled thereby. However, the code inside those blocks is still compiled (unlike the preprocessor) and subject to syntax checks. I sometimes find it annoying that #import
s used by constant-commented-out code are declared (in my Eclipse IDE) to be unused, yet if I leave out the #import
then my coding will be incorrect if I change the constants.
Note that this "constant" can be defined in a separate class, so changing your "configuration" could be accomplished by changing a value in a single file.
A more higher-level answer to your question involves run-time configuration, dependency injection, that kind of thing. The basic idea is to have your system-dependent code contained in separate classes (one for each target system), all of which implement the same interface(s).
At run time, about two different mechanisms come to mind for selecting the correct code:
Your code has a field whose type is that of the common interface; at startup, your program reads the name of the appropriate class from a configuration file, instantiates an object of that class using Class.forName()
or something similar, assigns that object to the field and then uses the methods on that instance to do whatever configuration-specific things need to be done.
If you're deploying your program as Jar
files, you can create separate Jar files containing one each of your config-dependent classes, and when you deploy your program, you deploy a "main" jar file and one jar file with the config-dependent stuff. Then when your program runs it can search its classpath for any of the candidate classes (perhaps by doing trial-and-error with Class.forName()
) and then it works similarly to the other mechanism.
EDIT
Thinking about this, I thought of a "Zen Buddhist meta-answer":
In the gluttonous boundlessness of memory occupied by a Java program, why worry about a few bytes of superfluous code? If you really only want to code two alternative approaches to executing a system-dependent command, then heck, code and compile separate methods for each one:
private void windowsProcess();
private void linuxProcess();
...and then call whichever one is appropriate:
public void independentProcess() {
if (runningOnWindows()) {
windowsProcess();
} else {
linuxProcess();
}
}
...and be done with it.
Separate Jars, runtime resolution and so forth are solutions aimed at exchanging significant parts of code machinery, whole libraries perhaps... if it's just a few hundred lines or so, I personally would not worry about the unused code in my program. It's not Java-like to be fastidious about small or even medium amounts of memory. What's the memory overhead of every object? 16 bytes? 32?