Is there a way to define flags in java and run the code only if these flags are defined?

In c\c++ you can define:

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

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

thanks!

+8
java
source share
6 answers

Answer: No. Not in the sense of what you mean.

How do you do similar things in Java as follows:

 private static final boolean flag = true; /* or false :-) */ if (flag) { /* code */ } else { /* different code */ } 

There is no preprocessor in Java (e.g. C and C ++ do). However, the compiler optimizes the unused branch of the if , as indicated above, Provides that flag is an expression of a compile-time constant. This is a limited form of conditional compilation. Note that the control constant flag can be imported from another class.

(IIRC, this behavior is specified in JLS ... this means that you can rely on any appropriate Java compiler to do this.)


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

  • If @Treebranch talks about inflating object code, this is not true. If you do this correctly with flags / expressions, which are constant compile-time expressions, as defined by JLS, then the compiler does not emit bytecodes for the "conditionally excluded" source code. See @edalorso's answer.

  • If @Treebranch talks about bloating source code, I agree. But you can say the same for conditional compilation of #ifdef . (Macros and #include can be used to reduce bloating of the source code ... but only at the cost of readability, maintainability, etc. And for this reason, the Java developers refused to support preprocessing of the source code.)

  • Java has the best way to resolve platform differences, features, etc: use dynamic binding. If your JAR has many different classes of plugins, you can handle this by creating a different JAR file for each platform or something else.

+6
source share

An approach that assumes that the use of a finite static logical variable is closest to this proposed function, since 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 you 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 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 off the flag ...

 private static final boolean DEBUG = false; 

Bytecodes are 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 closest to what you can get in the precompile directive in Java.

+4
source share

The one you trimmed above was a conditional compilation macro designed for a preprocessor that β€œconverts” your source code before compilation.

Java does not have an equivalent language construct, so anser you cannot do this.

Edit: However, you can use the usual conditions to achieve your goal, since in this way the compiler will optimize the bytecode in the way you need (thanks for @StephenC for pointing this out).

But I personally prefer to extend the API for debugging where necessary, which will hide implementation details and can be changed by runtime. Of course, it depends on the scenario.

For example, it will be similar to the Log4j-s API , which allows you to check whether your code is in debug mode or not.

I would recommend using this template because it does not violate (too much :) our favorite object-oriented concepts.

0
source share

In Java, there is nothing like conditional compilation. (as hea said)

Depending on the problem you want to solve, there are various ways to do something like this.

One of them is to use a static final variable set for a compile-time constant (as Stephen writes). The compiler will not actually include byte code for the impossible path. But it still needs to be legal java, which means that you cannot declare a variable in one such block and use it in another.

I have all the cases that I have seen so far, could solve this using OO constructs. For example, you can replace your if else with an abstract method call and provide a debugging and production implementation.

0
source share

Java as a language does not have similar preprocessing or macros, such as C or C ++, however there is some third-party preprocessor - tools that can handle such things. For convenient use, you need to connect them to Maven- or Ant -build.

0
source share

I think the proposed @StephenC is a good option. Alternatively, you can try using AspectJ to bind in the code that is required for a particular implementation. Then you can simply remove the aspect (not interweave in the code) when you don't want it to be part of the implementation. AspectJ modifies the bytecode (compiled Java code) based on the types of locations (called pointcuts) that you specify. This is especially good for things like adding registration to your program.

If this is your approach, check out: AspectJ and the Reference Guide .

0
source share

All Articles