2009-12-18 3 views
62

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

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

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

+8

В современном C++ вы должны использовать типизированную константу, а не #define для этого –

+2

Да, #define - это C-стиль. В C++ вместо этого используйте const. См. Книгу Скотта Мейерса «Эффективный С ++», пункт 1. – Jabba

ответ

84

Нет, потому что нет прекомпилятора.

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

class MyClass 
{ 
    private static final int PROTEINS = 0; 

    ... 

    MyArray[] foo = new MyArray[PROTEINS]; 

} 

компилятор заметит, что PROTEINS никогда не может, когда-нибудь изменится и так будет inline, который более или менее то, что вы хотите.

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

+13

Это отвечает на вопрос, но неправильно использует несколько терминов. Inline выполняется во время выполнения, когда компилятор JIT замечает, что метод достаточно прост и не переопределен (я не знаю всех правил и может меняться от версии к версии). «Статический окончательный» примитивный или строковый тип определяется спецификацией компилятора Java (не JIT) как константа. Он не «встроен» в смысле JIT, он фактически непосредственно скомпилирован в ту часть кода, что и #define находится в C. –

5
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; 

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

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

+0

Ну, * private * 'static finals' на самом деле не является частью * открытого * интерфейса. :) Для 'public static finals' это правда. – Bombe

+0

@Mombe, правильный. Я написал его изначально как общедоступный, но затем изменил без обновления ответа. – notnoop

34

Комментарий слишком маленький, так что вот вам дополнительная информация по использованию static final. Как я уже сказал в своем комментарии к Andrzej's answer, только примитив и 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); 
    } 
} 

компилировать их и запустить тест, который печатает:

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"); 
} 

Run Test без перекомпиляции 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, тогда это будет так.

+1

Определенно +1 для усилий! –

+0

Просто хочу добавить, что java не делает то же самое для 'enum'. –

0

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

0

Большинство читается Решение использует Static Import. Тогда вы будете не необходимо использовать 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; 

    } 
} 

Чтобы узнать больше о Static Импорт см this stack overflow question.

2

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

Смежные вопросы