Произвести условную ошибку времени компиляции в Java
-
01-07-2019 - |
Вопрос
Я не имею в виду ошибки компиляции, потому что я допустил синтаксическую ошибку или что-то еще.В C++ мы можем создавать ошибки времени компиляции в зависимости от условий, как показано в следующем примере:
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) { CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
int main(int argc, char* argv[])
{
STATIC_CHECK(false, Compile_Time_Failure);
return 0;
}
В VS 2005 это выведет:
------ Build started: Project: Test, Configuration: Debug Win32 ------
Compiling...
Test.cpp
f:\temp\test\test\test.cpp(17) : error C2079: 'ERROR_Compile_Time_Failure' uses undefined struct 'CompileTimeError<__formal>'
with
[
__formal=0
]
Build log was saved at "file://f:\temp\Test\Test\Debug\BuildLog.htm"
Test - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Есть ли способ добиться этого на Java?
Решение
В Java это невозможно сделать, как и в C++.
Возможно, вы могли бы использовать аннотации и запустить подходящий до или после компиляции, чтобы проверить ваши аннотации.
Например:
@MyStaticCheck(false, "Compile Time Error, kind-of")
public static void main(String[] args) {
return;
}
А затем напишите свою собственную AnnotationProcessorFactory, которая ищет аннотации @MyStaticCheck и что-то делает с аргументами.
Примечание:Я не слишком много играл с apt, но из документации видно, что это вполне выполнимо.
Другие советы
В Java невозможно выполнить какие-либо действия на основе логики времени компиляции без использования отдельного инструмента.Технически это возможный использовать препроцессор C на Java, но вам придется быть осторожным с его встроенными предположениями о базовом языке.На вашем месте я бы нашел лучший способ добиться того, что вы пытаетесь сделать, с этой ошибкой времени компиляции.При необходимости вы даже можете написать свой собственный препроцессор (возможно, используя АПТ), если это действительно так неизбежно.
Как ответил Мэтт Куэйл выше, аннотации вместе с XDoclet, подходят для удовлетворения ваших потребностей.Эти комбинации позволяют выполнить значительную предварительную обработку, генерацию кода и т. д.
Хотя вопрос был задан некоторое время назад, я решил опубликовать свой ответ, потому что решил (в определенной степени) немного похожую проблему.
Специфика моей задачи требует, чтобы два приложения с разным набором функций были построены из одной базовой библиотеки (и неиспользуемые элементы не должны быть связаны).Выбор набора функций осуществляется public static final boolean
флаги.Проблема в том, что я хочу убедиться, что каждое из приложений построено с правильным флагом, установленным в базовой библиотеке.А в случае включения неправильных функций приложение не должно компилироваться, выдавая ошибку времени компиляции.
Единственное решение, которое я нашел до сих пор, — это объявить в библиотеке конечные переменные вместе с флагами: public static final int functionSet1 = 0;
, и т. д.
В пакет приложения я добавил фиктивный класс с проверкой
ConditionalBuild.functionSet1 = 1;
Из всех переменных functionSetX только одна стала нефинальной в конкретной сборке.Таким образом, только одно приложение может пройти процесс сборки без ошибки.Есть ли лучший способ добиться этого?Пожалуйста, дайте мне знать в комментариях.