Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a way to define flags in java and run code only if those flags are defined?

Tags:

java

In c\c++ can define:

#ifndef <token>
    /* code */
#else
    /* code to include if the token is defined */
#endif

my question, is there a way to do it in java? (which is not defining a global static variable..) for example i want to run some code only in debug mode..

thanks!

like image 285
Asher Saban Avatar asked Mar 24 '12 09:03

Asher Saban


2 Answers

The answer is No. Not in the sense that you mean.

The way you do this kind of thing in Java as follows:

private static final boolean flag = true;  /* or false :-) */

if (flag) {
   /* code */
} else {
   /* different code */
}

Java doesn't have a preprocessor (like C and C++ do). However, the compiler will optimize away the unused branch of an if statement like the above, PROVIDED that flag is a compile-time constant expression. This is a limited form of conditional compilation. Note that the controlling flag constant can be imported from a different class.

(IIRC, this behaviour is specified in the JLS ... which means that you can rely on any conforming Java compiler to do it.)


@Treebranch comments that "this" can cause code bloat.

  1. If @Treebranch is talking about object code bloat, this is not true. If you do this right with flags/expressions that are compile-time constant expressions as defined by the JLS, then the compiler does not emit any bytecodes for the "conditionally excluded" source code. See @edalorso's answer.

  2. If @Treebranch is are talking about source-code bloat, I agree. But you can say the same thing for #ifdef conditional compilation. (Macros and #include can be used to reduce source-code bloat ... but only at the cost of readability, maintainability, etc. And that was the reason that the Java designers refused to support any source-code preprocessing.)

  3. Java has a better way of dealing with platform differences, functionality variations and so on: use dynamic binding. If having lots of different plugin classes in your JAR is a concern (bytecode bloat), deal with it by creating a different JAR file for each platform, or whatever.

like image 183
Stephen C Avatar answered Oct 18 '22 23:10

Stephen C


The approach that suggest that use of final static boolean variable is the closest to that suggested feature because it is even optimized by the compiler. If the flag is set to false the bytecodes contained in the block are not even generated.

Let me show an example:

public class Optimized {

    private static final boolean DEBUG = true;

    public static void main(String[] args) {
        if(DEBUG){
            System.out.println("DEBUG enabled");
        }
    }

}

This generates the bytecodes

public class Optimized {
  public Optimized();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String DEBUG enabled
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

But if we turn the flag off...

private static final boolean DEBUG = false;

The bytecodes look as follows

public class Optimized {
  public Optimized();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: return
}

So, AFAIK, this is the closest you can get to a precompile directive in Java.

like image 30
Edwin Dalorzo Avatar answered Oct 18 '22 23:10

Edwin Dalorzo