#определить в Java

Я начинаю программировать на Java, и мне интересно, существует ли эквивалент C++ #define.

Быстрый поиск в google говорит, что это не так, но может ли кто-нибудь сказать мне, существует ли что-то подобное в Java? Я пытаюсь сделать свой код более читабельным.

Вместо myArray[0] я хочу, например, написать myArray[PROTEINS].


person Meir    schedule 18.12.2009    source источник
comment
В современном С++ вы должны использовать для этого типизированную константу, а не #define.   -  person Pete Kirkham    schedule 18.12.2009
comment
Да, #define — это C-стиль. В С++ вместо этого используйте const. См. книгу Скотта Мейерса «Эффективный C++», пункт 1.   -  person Jabba    schedule 18.12.2009


Ответы (9)


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

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

Компилятор заметит, что PROTEINS никогда не может измениться, и поэтому встроит его, что более или менее то, что вам нужно.

Обратите внимание, что модификатор доступа к константе здесь не важен, поэтому он может быть public или protected вместо private, если вы хотите повторно использовать одну и ту же константу в нескольких классах.

person Andrzej Doyle    schedule 18.12.2009

Место для комментариев слишком маленькое, поэтому вот еще немного информации об использовании static final. Как я сказал в своем комментарии к ответу Анджея, только примитивы и String компилируются напрямую в код как литералы. Чтобы продемонстрировать это, попробуйте следующее:

Вы можете увидеть это в действии, создав три класса (в отдельных файлах):

public class DisplayValue {
    private String value;

    public DisplayValue(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
}

public class Constants {
    public static final int INT_VALUE = 0;
    public static final DisplayValue VALUE = new DisplayValue("A");
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Int   = " + Constants.INT_VALUE);
        System.out.println("Value = " + Constants.VALUE);
    }
}

Скомпилируйте их и запустите Test, который напечатает:

Int    = 0
Value  = A

Теперь измените Constants, чтобы у каждого было другое значение, и просто скомпилируйте класс Constants. Когда вы снова выполняете Test (без перекомпиляции файла класса), он по-прежнему печатает старое значение для INT_VALUE, но не VALUE. Например:

public class Constants {
    public static final int INT_VALUE = 2;
    public static final DisplayValue VALUE = new DisplayValue("X");
}

Запустить тест без перекомпиляции Test.java:

Int    = 0
Value  = X

Обратите внимание, что любой другой тип, используемый с static final, сохраняется в качестве ссылки.

Подобно C/C++ #if/#endif, константный литерал или литерал, определенный через static final с примитивами, используемый в обычном условии Java if и оцениваемый как false, заставит компилятор удалить байтовый код для операторов в блоке if (они будут не генерироваться).

private static final boolean DEBUG = false;

if (DEBUG) {
    ...code here...
}

Код в "...code here..." не будет скомпилирован в байтовый код. Но если бы вы изменили DEBUG на true, то так и было бы.

person Kevin Brock    schedule 18.12.2009
comment
Определенно +1 только за усилия! - person Andreas Dolk; 18.12.2009
comment
Просто хочу добавить, что java не делает то же самое для enums. - person artronics; 03.05.2016

static final int PROTEINS = 1
...
myArray[PROTEINS]

Обычно вы помещаете «константы» в сам класс. И обратите внимание, что компилятору разрешено оптимизировать ссылки на него, поэтому не изменяйте его, если вы не перекомпилируете все используемые классы.

class Foo {
  public static final int SIZE = 5;

  public static int[] arr = new int[SIZE];
}
class Bar {
  int last = arr[Foo.SIZE - 1]; 
}

Цикл редактирования... SIZE=4. Также скомпилируйте Bar, потому что ваш компилятор мог только что написать "4" в последнем цикле компиляции!

person extraneon    schedule 18.12.2009

В Java нет общей директивы препроцессора define.

В случае с константами рекомендуется объявлять их как static finals, как в

private static final int PROTEINS = 100;

Такие объявления будут встроены компиляторами (если значение является константой времени компиляции).

Также обратите внимание, что общедоступные статические конечные константные поля являются частью общедоступного интерфейса, и их значения не должны изменяться (поскольку компилятор их встраивает). Если вы измените значение, вам нужно будет перекомпилировать все источники, которые ссылаются на это постоянное поле.

person notnoop    schedule 18.12.2009
comment
Ну, private static finals на самом деле не является частью public интерфейса. :) Хотя для public static finals это верно. - person Bombe; 18.12.2009
comment
@ Момбе, верно. Сначала я написал его как общедоступный, но затем изменил, не обновив ответ. - person notnoop; 18.12.2009

Существует препроцессор для Java, который предоставляет такие директивы, как #define, #ifdef, #ifndef и многие другие, например, команда PostgresJDBC использует его для генерации исходников для разных случаев и для того, чтобы не дублировать код.

person Igor Maznitsa    schedule 18.01.2018

Самое удобочитаемое решение использует Статический импорт. Тогда вам не нужно будет использовать AnotherClass.constant.

Напишите класс с константой в виде поля public static.

package ConstantPackage;

public class Constant {
    public static int PROTEINS = 1;
}

Затем просто используйте Статический импорт там, где вам нужна константа.

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

        int[] myArray = new int[5];
        myArray[PROTEINS] = 0;

    }
}

Чтобы узнать больше о статическом импорте, см. этот вопрос о переполнении стека .

person Md. Abu Nafee Ibna Zahid    schedule 02.01.2018

препроцессор Manifold, реализованный как javac Подключаемый модуль компилятора предназначен исключительно для условной компиляции исходного кода Java. Он использует знакомый стиль директив C/C++: #define, #undef, #if, #elif, #else, #endif, #error. и #предупреждение.

Он имеет плагины Maven и Gradle.

person Pavlo Maistrenko    schedule 05.07.2020

Самый простой ответ: "Нет прямого метода получения, потому что нет предварительного компилятора" Но вы можете сделать это самостоятельно. Используйте классы, а затем определите переменные как final, чтобы их можно было считать постоянными во всей программе
Не забудьте использовать final и переменные как общедоступные или защищенные. не частный, иначе вы не сможете получить к нему доступ из-за пределов этого класса

person Jitendra Nagar    schedule 30.05.2017

Генератор примитивных специализаций Java поддерживает блоки /* with */, /* define */ и /* if */ ... /* elif */ ... /* endif */, которые позволяют выполнять некоторые тип генерации макросов в коде Java, аналогичный препроцессору java-comment-preprocessor, упомянутому в этом ответе.

JPSG имеет плагины Maven и Gradle.

person leventov    schedule 08.04.2019