Возможно ли статическое метапрограммирование в Java? - PullRequest
36 голосов
/ 22 сентября 2008

Я фанат статического метапрограммирования в C ++ . Я знаю, что в Java сейчас есть дженерики. Означает ли это, что статическое метапрограммирование (то есть выполнение программы во время компиляции) возможно в Java? Если да, может кто-нибудь порекомендовать какие-нибудь хорошие ресурсы, где можно узнать больше об этом?

Ответы [ 10 ]

24 голосов
/ 22 сентября 2008

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

Редактировать: Это старый ответ; с 2011 года у нас есть Java 7, которая имеет аннотации, которые можно использовать для такой хитрости .

12 голосов
/ 22 сентября 2008

Взгляните на Clojure . Это LISP с макросами (метапрограммирование), который работает на JVM и очень совместим с Java.

5 голосов
/ 09 декабря 2010

Что именно вы подразумеваете под «статическим метапрограммированием»? Да, метапрограммирование шаблона C ++ невозможно в Java, но оно предлагает другие методы, гораздо более мощные, чем в C ++:

  • отражение
  • аспектно-ориентированное программирование (@AspectJ)
  • манипулирование байт-кодом (Javassist, ObjectWeb ASM, агенты Java)
  • генерация кода (инструмент для обработки аннотаций, шаблонизаторы, такие как Velocity)
  • Абстрактные манипуляции с синтаксическим деревом (API предоставлены популярными IDE)
  • возможность запуска компилятора Java и использования скомпилированного кода даже во время выполнения

Нет лучшего метода: каждый из этих методов имеет свои сильные и слабые стороны. Благодаря гибкости JVM все эти методы в Java могут использоваться как во время компиляции, так и во время выполнения.

3 голосов
/ 22 сентября 2008

Нет. Более того, универсальные типы стираются компилятором до их верхней границы, поэтому вы не можете создать новый экземпляр универсального типа T во время выполнения.

Лучший способ выполнить метапрограммирование в Java - обойти стирание типа и передать объект Class<T> вашего типа T. Тем не менее, это всего лишь взлом.

2 голосов
/ 16 сентября 2010

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

http://www.github.com/blak3mill3r

Это библиотека для генерации кода Java, написанная на Ruby, которую я написал для автоматической генерации интерфейсов Google Web Toolkit для приложений Ruby on Rails. Это оказалось весьма удобным для этого.

В качестве предупреждения может быть очень сложно отладить код Rjava, Rjava не выполняет много проверок, он просто предполагает, что вы знаете, что делаете. Это в значительной степени состояние статического метапрограммирования в любом случае. Я бы сказал, что его значительно легче отлаживать, чем что-либо нетривиальное, сделанное с C ++ TMP, и его можно использовать для тех же целей.

В любом случае, если вы планируете написать программу, которая выводит исходный код Java, остановитесь прямо сейчас и посмотрите Rjava. Возможно, он еще не делает то, что вы хотите, но у него есть лицензия MIT, так что не стесняйтесь его улучшать, жарить или продавать его своей бабушке. Я был бы рад, если бы другие разработчики, имеющие опыт работы с общим программированием, могли прокомментировать дизайн.

2 голосов
/ 22 сентября 2008

Нет, дженерики в Java - это просто способ избежать приведения Object.

1 голос
/ 12 августа 2013

Lombok предлагает слабую форму метапрограммирования времени компиляции. Тем не менее, техника, которую они используют, является полностью общей .

См. Преобразование кода Java во время компиляции для соответствующего обсуждения

1 голос
/ 23 сентября 2008

В очень сокращенном смысле, может быть? http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/

0 голосов
/ 20 мая 2019

Проект Manifold предлагает метапрограммирование для безопасных типов * static для Java. Вы можете использовать его для динамического построения типов во время компиляции, поскольку Javac разрешает имена типов. Демонстрация JSON Schema демонстрирует статическое метапрограммирование в терминах динамической проекции типа во время компиляции (без этапов сборки кода).

Кроме того, вы можете использовать коллектор для добавления новых функций. Проверьте Структурная типизация , Расширения метода и Отражение безопасного типа . .

0 голосов
/ 26 февраля 2010

Я не уверен, что понимаю преимущество статического метапрограммирования.

В Java вы можете подумать, чтобы найти информацию о ваших классах и сделать все то, что сделает метапрограммирование, вы просто выполняете их внутри своего кода, не добавляя новый синтаксис и различные способы мышления. Аннотации также могут выполнять определенные задачи метапрограммирования более структурированным образом.

Я могу ошибаться, я серьезно думаю об открытии вопроса, потому что я не уверен, что понял. Кажется, что статическое метапрограммирование - это аккуратный хак, который обходит тот факт, что некоторые языки не хранят много информации времени компиляции, доступной во время выполнения (одна из сильных сторон Java и динамических языков).

Если бы кто-нибудь мог ответить со ссылкой на пример, где метапрограммирование предлагает более понятное, читаемое или иное лучшее решение, чем рефлексия, я был бы признателен за усилия.

...