#define в Java

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

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

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

Ответ 1

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

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

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

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

Ответ 2

Слишком мало места для комментариев, так что вот вам еще немного информации об использовании static final. Как я сказал в своем комментарии к ответу Andrzej, только примитив и 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...
}

Код в "... код здесь..." не будет скомпилирован в байт-код. Но если бы вы изменили DEBUG на true тогда это было бы так.

Ответ 3

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" в последнем цикле компиляции!

Ответ 4

Java не имеет директивы препроцессора общего назначения define.

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

private static final int PROTEINS = 100;

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

package ConstantPackage;

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

Тогда просто используйте Static Import там, где вам нужна константа.

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

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

    }
}

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

Ответ 8

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

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