#ifdef #ifndef в Java

Я сомневаюсь, что есть способ сделать условия компиляции в Java, например #ifdef #ifndef в С++.

Моя проблема в том, что есть алгоритм, написанный на Java, и у меня есть другое время работы, которое улучшает этот алгоритм. Поэтому я хочу определить, сколько времени я сохраняю, когда используется каждое улучшение.

Прямо сейчас у меня есть набор логических переменных, которые используются для решения в течение времени выполнения, которое должно быть использовано, а что нет. Но даже тестирование этих переменных влияет на общее время работы.

Итак, я хочу узнать, как решить во время компиляции, какие части программы должны быть скомпилированы и использованы.

Кто-нибудь знает способ сделать это на Java. Или, может быть, кто-то знает, что такого пути нет (это также было бы полезно).

Ответ 1

private static final boolean enableFast = false;

// ...
if (enableFast) {
  // This is removed at compile time
}

Условные выражения, подобные приведенным выше, оцениваются во время компиляции. Если вместо этого вы используете этот

private static final boolean enableFast = "true".equals(System.getProperty("fast"));

Тогда любые условия, зависящие от enableFast, будут оцениваться компилятором JIT. Накладные расходы для этого незначительны.

Ответ 2

javac не выводит скомпилированный код, недоступный. Используйте конечную переменную, установленную в постоянное значение для #define и нормального выражения if для #ifdef.

Вы можете использовать javap, чтобы доказать, что недостижимый код не включен в файл выходного класса. Например, рассмотрим следующий код:

public class Test
{
   private static final boolean debug = false;

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

javap -c Test дает следующий вывод, указывающий, что только один из двух путей был скомпилирован (и оператор if не был):

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

Ответ 3

Я думаю, что нашел решение, это намного проще.
Если я определяю логические переменные с "финальным" модификатором, сам компилятор Java решает проблему. Потому что он заранее знает, что было бы результатом проверки этого состояния. Например, этот код:

    boolean flag1 = true;
    boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }

работает около 3 секунд на моем компьютере.
И этот

    final boolean flag1 = true;
    final boolean flag2 = false;
    int j=0;
    for(int i=0;i<1000000000;i++){
        if(flag1)
            if(flag2)
                j++;
            else
                j++;
        else
            if(flag2)
                j++;
            else
                j++;
    }

работает около 1 секунды. В то же время этот код принимает

    int j=0;
    for(int i=0;i<1000000000;i++){
        j++;
    }

Ответ 4

Никогда не использовал его, но это существует

JCPP является полным, совместимым, автономная, чистая реализация Java препроцессора C. Он предназначен для использования людьми, пишущими C-style компиляторы в Java, используя такие инструменты, как sablecc, antlr, JLex, CUP и так далее вперед. Этот проект был использован для успешного препроцесса большей части исходный код библиотеки GNU C. В виде версии 1.2.5, он также может препроцесс Apple Objective C библиотека.

http://www.anarres.org/projects/jcpp/

Ответ 5

Если вам действительно нужна условная компиляция, и вы используете Ant, вы можете фильтровать свой код и выполнять поиск и замену в нем.

Например: http://weblogs.java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html

Таким же образом вы можете, например, написать фильтр, чтобы заменить LOG.debug(...); на /*LOG.debug(...);*/. Это все равно будет выполняться быстрее, чем if (LOG.isDebugEnabled()) { ... }, не говоря уже о краткости в одно и то же время.

Если вы используете Maven, здесь описывается аналогичная функция .

Ответ 6

Использовать шаблон Factory для переключения между реализациями класса?

Время создания объекта не может быть проблемой сейчас? Когда усредняется в течение длительного периода времени, самая большая составляющая времени должна быть в основном алгоритме, не так ли?

Строго говоря, вам не нужен препроцессор, чтобы делать то, что вы добиваетесь. Скорее всего, есть другие способы удовлетворить ваши требования, чем тот, который я предложил, конечно.

Ответ 7

Коллектор предоставляет полностью интегрированный препроцессор Java (без этапов сборки или сгенерированного источника). Он предназначен исключительно для условной компиляции и использует директивы в стиле C.

Manifold's Java Preprocessor

Ответ 8

final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0