Java условная компиляция с подклассами
Мои извинения, если это уже спрашивали где-то еще, но я не мог найти это.
По сути, я хотел бы знать, будет ли работать класс Java с условной компиляцией (с целью удаления всех следов фрагмента кода в файлах классов) на его подклассах.
Например, давайте реализуем класс A и его подкласс B следующим образом:
Понятно, что ничего не будет распечатано. Но будут ли их файлы классов включать скомпилированное условие if?
4 ответа
Вы должны попытаться создать файлы .class, а затем декомпилировать его с помощью декомпилятора или просто зайти на javadecompilers.com и загрузить файл класса, чтобы подтвердить свой ответ.
Если сделать исходники на основе вашего кода
И скомпилировать с javac, затем с FALSE у нас есть байт-код
С TRUE мы получаем скомпилированный байт-код ниже
Так что на уровне javac такая оптимизация работает, но для гарантии лучше удалить части кода на уровне источников перед компиляцией, например, с помощью препроцессор
Просто скомпилировал класс в IntelliJ, затем декомпилировал файл .class , чтобы увидеть, содержит ли он оператор (ы). Это не так.
Я подозреваю, что это зависит от компилятора (то есть Спецификация языка Java не делает никаких заявлений о том, должны ли эти вещи быть включены, поэтому они могут свободно выбирать), и что вы, вероятно, могли бы найти компилятор, который будет включите эти заявления однако. Я использовал Corretto Java 11.
Java не поддерживает такие макросы, как c, c ++. Вы можете использовать флаги для включения или отключения утверждений во время выполнения, но без макросов
Источник
Условная компиляция Java
Я давний программист на C ++, новичок в Java. Я разрабатываю проект Java Blackberry в Eclipse. Вопрос — есть ли способ ввести различные наборы конфигурации в проект, а затем скомпилировать немного другой код на их основе?
В Visual Studio у нас есть настройки проекта и #ifdef; Я знаю, что в Java нет #ifdef, но, возможно, что-то на уровне файлов?
10 ответов
Вы можете установить поля ‘final’ и ifs, чтобы компилятор оптимизировал скомпилированные байт-коды.
Если myFinalVar имеет значение false, когда код скомпилирован, бит «сделать что-то . » будет пропущен в скомпилированном классе. Если у вас есть более одного условия — это можно немного привести в порядок: переместите их все в другой класс (скажем, «Config.myFinalVar»), и тогда все условия можно будет сохранить в одном удобном месте.
Этот механизм описан в ‘Hardcore Java’.
[На самом деле, я думаю, что это тот же механизм, что и ранее опубликованный «ifdef для бедняков».]
вы можете управлять различными путями к классам, например, реализовывать каждое действие в наборе отдельных каталогов:
затем используйте разные пути к классам для каждой версии
Если вы хотите это специально для BlackBerry, JDE для BlackBerry имеет препроцессор :
Вам может включить предварительную обработку для вашего приложений путем обновления Eclipse ™ файл конфигурации.
В C: \ Program Files \ Eclipse \ configuration \ config.ini, добавьте следующую строку: osgi.framework.extensions = net.rim.eide.preprocessing.hook Если вы включите предварительную обработку после у вас был билд, вы должны очистить проект из меню проекта до Вы строите проект снова.
Тогда вы можете делать такие вещи в коде, как:
В JDK6 вы можете сделать это с помощью интерфейса Java ServiceLoader. Проверьте это здесь .
Нет, у Java нет точного соответствия этой функциональности. Вы можете использовать аспекты или использовать контейнер IOC для внедрения различных классов реализации.
Вы можете интегрировать m4 в процесс сборки, чтобы эффективно привязать аналог препроцессора C к компилятору Java. Большая часть размахивания руками лежит на этапе «интеграции», но m4 — подходящая технология для работы по обработке текста.
Помимо Maven, Ant и других инструментов сборки, которые предоставляют аналогичную функциональность, лучше было бы создавать интерфейсы в Java и переключать реализации во время выполнения.
См. шаблон стратегии для получения дополнительной информации
В отличие от C /C ++ это не приведет к значительному снижению производительности, поскольку JIT-компилятор Javas оптимизирует во время выполнения и в большинстве случаев может использовать эти шаблоны.
Основным преимуществом этого шаблона является гибкость — вы можете изменить базовую реализацию, не затрагивая основные классы.
Вам также следует проверить IoC и Шаблон наблюдателя для получения дополнительной информации.
Вы можете использовать фильтрацию ресурсов maven в сочетании с открытыми статическими полями final, которые действительно будут скомпилированы условно.
Теперь вам нужно добавить свойство в свой maven pom под названием «mode», которое должно быть того же значения, что и ваша константа ANDROID.
Java-компилятор должен (!) удалить блоки if и else, оставляя ваш код Android.
Не тестируйте, поэтому нет никаких гарантий, и я бы предпочел конфигурацию вместо условной компиляции.
В Eclipse вы можете использовать несколько проектов
- Main (содержит общий код)
- Версия1 (содержит код версии1)
Версия2 (содержит код версии2)
- Main -> Выберите Project -> Properties -> Java Build Path -> вкладка Projects
- Выберите Добавить .
- Добавьте «Version1» или «Version2» и нажмите «ОК» в рабочей области.
Версия1 и Версия два содержат одни и те же файлы, но разные реализации. В Main вы обычно пишете, например.
Источник
Условная компиляция в Android?
Существует ли какая-либо условная компиляция для Android?
Я должен был сделать свой проект для Android 3 (API 11) только потому, что ExifInterface почти не имеет полезных атрибутов в Android 2.3 (API 10), несмотря на то, что он появился в API 5 (!! ??). Я не хочу ограничивать свое приложение для пользователей ICS.
Вы можете динамически проверять текущую версию API-устройства и делать разные вещи в зависимости от этого:
Но будьте осторожны, если вам нужно создать экземпляры классов, которые недоступны для всех API, тогда вы должны сделать это в runnable или в отдельном классе-оболочке, например:
А затем использовать аннотации:
Использование этого трюка делает очень простую вещь: он позволяет компилировать некоторый код, который содержит вызовы уровня 11 API (классы, методы и т. Д.), И все еще установить android:minSdkVersion=»8″ в манифесте. Ничего больше, больше ничего.
Остальное зависит от тебя. Вы должны проверить версию платформы, прежде чем вы вызове methodUsesAPI11() или будете обрабатывать исключения, чтобы предотвратить сбой приложения и выполнить другие действия на старых платформах.
Проверка Build.VERSION.SDK_INT или использование аннотаций должна быть достаточной, однако эта ссылка, которую я добавил в закладки, может иметь отношение к вашему делу: http://android-developers.blogspot.com/2010/07/how-to-have-your -cupcake-и пожирают его-too.html? т = 1
Вы можете использовать то, что они там описывают, чтобы иметь классы, которые могут быть несовместимы, но никогда не будут загружены. Это не условная компиляция, но это может быть то, что вам нужно, однако, это немного сложнее.
Источник
Условная компиляция Java: как предотвратить компиляцию фрагментов кода?
мой проект требует Java 1.6 для компиляции и запуска. Теперь у меня есть требование, чтобы он работал с Java 1.5 (со стороны маркетинга). Я хочу заменить тело метода (возвращаемый тип и аргументы остаются теми же), чтобы сделать его компиляции с Java 1.5 без ошибок.
детали: у меня есть служебный класс под названием OS который инкапсулирует все специфические для ОС вещи. У него есть метод
чтобы открыть файлы, как с двойным щелчком мыши ( start команда Windows или open эквивалент команды Mac OS X). Поскольку он не может быть скомпилирован с Java 1.5, я хочу исключить его во время компиляции и заменить другим методом, который вызывает run32dll или open для Mac OS X с помощью Runtime.exec .
вопрос: Как я могу это сделать? Могут ли аннотации помочь здесь?
Примечание: я использую ant, и я могу сделать два java-файла OS4J5.java и OS4J6.java , который будет содержать OS класс с требуемым кодом для Java 1.5 и 1.6 и скопируйте один из них OS.java перед компиляцией (или уродливым способом — заменить контент OS.java условно-в зависимости от версии Java), но я не хочу этого делать, если есть другой путь.
разработка больше: в C я мог бы использовать ifdef, ifndef , в Python нет компиляции и я мог бы проверить с помощью hasattr или что-то еще, в общем Lisp я мог бы использовать #+feature . Есть ли что-то подобное для Java?
нашел этот пост но это не кажется полезным.
любая помощь очень ценится. х.
7 ответов
нет в Java нет никакой поддержки условной компиляции.
обычный план состоит в том, чтобы скрыть конкретные биты ОС вашего приложения за Interface а затем обнаружить тип ОС во время выполнения и загрузить реализацию с помощью Class.forName(String) .
в вашем случае нет причин, по которым вы не можете скомпилировать оба OS* (и воздействовать на все приложение) с помощью Java 1.6 с -source 1.5 -target 1.5 затем в Заводском методе для получения OS классы (которые теперь будут интерфейсом) обнаружить это java.awt.Desktop класс доступен и загрузить правильную версию.
скрытие двух классов реализации за интерфейсом, как предложил Гарет, вероятно, лучший способ пойти.
тем не менее, вы можете ввести своего рода условную компиляцию, используя задачу replace в сценариях сборки ant. Хитрость заключается в использовании комментариев в коде, которые открываются / закрываются текстовой заменой непосредственно перед компиляцией источника, например:
теперь в ant, когда вы компилируете для Java 6, Замените «IFDEF6» на «*/», дача:
и при компиляции для Java 5 Замените «IFDEF5». Обратите внимание, что вы должны быть осторожны, чтобы использовать // comments внутри /*<< , /*>> блоки.
скрипт Ant, представленный ниже, дает хороший и чистый трюк.
пожалуйста, перейдите по ссылке выше более подробно.
вы можете совершать вызовы с помощью отражения и компилировать код с помощью Java 5.
вы можете поймать любые исключения и вернуться к чему-то, что работает на Java 5.
Я не такой большой знаток Java, но кажется, что условная компиляция в Java поддерживается и легко сделать. Пожалуйста, прочитайте:
практика условной компиляции используется для необязательного удаления фрагментов кода из скомпилированной версии класса. Он использует тот факт, что компиляторы будут игнорировать любые недостижимые ветви кода. К реализовать условную компиляцию,
- определите статическое конечное логическое значение как не закрытый член некоторого класса
- поместите код, который должен быть условно скомпилирован в блоке if, который оценивает логическое
- установите значение логического значения в false, чтобы компилятор игнорировал блок if; в противном случае сохраните его значение как true
конечно, это позволяет нам «компилировать» куски кода внутри любого метод. Чтобы удалить члены класса, методы или даже целые классы (возможно, оставив только заглушку), вам все равно понадобится предварительный процессор.
на java 9 можно создавать файлы jar с несколькими выпусками. По сути это означает, что вы делаете несколько версий одного и того же файла Java.
когда вы компилируете их, вы компилируете каждую версию файла java с требуемой версией jdk. Далее вам нужно упаковать их в структуру, которая выглядит так:
в приведенном выше примере основная часть кода скомпилирована в java 8, но для java 9 есть дополнительная (но другая) версия из Utils класса.
когда вы запускаете этот код на java 8 JVM, он даже не проверяет классы в папке META-INF. Но в java 9 он будет, и будет находить и использовать более позднюю версию класса.
Если вы не хотите условно включенных блоков кода в вашем приложении, то препроцессор-это единственный способ, вы можете взглянуть на java-comment-препроцессор который может быть использован как для Maven и ant проектов
С. з.
и сделал некоторый пример использования предварительной обработки с Maven для создания JEP-238 multi-version JAR без дублирования источников
Источник
Java (Eclipse) – Условная компиляция
У меня есть проект java, на который ссылается проект j2me и проект андроида. В этом проекте я хотел бы использовать условную компиляцию.
Я читал об этом, но пока не нашел ничего полезного.
Вы можете использовать Антенну (есть плагин для Eclipse, и вы можете использовать его с системой сборки Ant). Я использую его в своих проектах так, как вы описали, и он отлично работает 🙂
EDIT: вот пример, связанный с решением @ WhiteFang34, который является способом:
В вашем основном проекте:
В вашем проекте, который использует основной проект:
Если вы хотите создать для Android, вы просто определяете символ препроцессора ANDROID или J2ME, если хотите сделать сборку для платформы J2ME …
Во всяком случае, я надеюсь, что это поможет 🙂
Возможно, вам стоит подумать о создании интерфейсов вокруг логики, характерной для профиля (J2ME, Android или другого в будущем). Затем создайте конкретные реализации вашего интерфейса для каждого профиля. Любые общие части, которые вы могли бы разделить на абстрактный базовый класс для обеих версий. Таким образом, ваша логика для каждого профиля прекрасно разделяется для разных проблем. Для каждого профиля просто создайте соответствующий набор классов (например, вы можете отделить их по пакету). В конечном итоге будет легче поддерживать, отлаживать, тестировать и понимать.
Проект Eclipse MTJ обеспечивает поддержку предварительной обработки, как описано . Эта поддержка была в основном направлена на решение проблем фрагментации JavaME. Я не тестировал поддержку предварительной обработки вместе с инструментами Android, но он может просто работать.
Источник