Генерация геттеров/сеттеров в Java (снова)

Я рассматриваю подходы к написанию


class MyClass {
  @Get
  @Set
  protected int aValue;
}

а затем автоматически сгенерировать методы get_aValue() и set_AValue() для класса.

Я нашел эти возможности:

1а) Во время компиляции. Используйте процессор аннотаций для отдельной обработки MyClass.java, затем напишите новый MyClass.java и, наконец, используйте этот последний (заменив оригинал) с остальной частью .java.

1b) Во время компиляции. Используйте процессор аннотаций для создания файла MyClassGenerated.java с новым классом (с методами get/set), являющимся подклассом исходного MyClass.

2) Во время работы. Используйте java.lang.instrument и внешний инструмент (например, BCEL), чтобы вплести новый код в MyClass.class.

Что ж, вопросы таковы: учитывая, что, насколько это возможно, я не хочу использовать сторонние библиотеки (например, проект lombok или BCEL)

а) Я пропускаю какой-либо другой подход?

б) Какой подход вы бы использовали?

Думаю, я буду использовать 1а), потому что

1b) не является чистым (остальная часть программы должна использовать MyClassGeneradted вместо оригинального MyClass, хотя, возможно, это только вопрос имен)

2) действительно сложно (для меня, по крайней мере).


person cibercitizen1    schedule 13.07.2010    source источник
comment
Не ходи сюда. В конце концов все библиотеки, которые вам нужны для написания кода, будут наступать друг другу на пятки и запрещать вам выполнять какую-либо работу. Очень похоже на то, когда графический интерфейс под Windows не позволяет вам делать то, что вам нужно.   -  person Thorbjørn Ravn Andersen    schedule 13.07.2010
comment
Правильные имена для методов доступа — getAValue и setAValue.   -  person whiskeysierra    schedule 14.07.2010


Ответы (6)


Вам что-то не хватает, и я бы сказал, что это лучший подход, если вы хотите пойти по этому пути:

1c) Во время компиляции. Скомпилируйте класс как обычно, затем используйте процессор аннотаций APT, чтобы изменить файл .class (не исходный файл), чтобы добавить в байт-код соответствующие методы get и set.

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


Тем не менее, это использование кувалды, чтобы открыть орех. Это выполнимо, но теперь ваш код не является строго Java в том смысле, что если кто-то возьмет его и запустит на нем javac, он получит класс без геттеров и сеттеров. Это затруднит отладку, так как все номера строк будут перепутаны, и если вы не уверены, что правильно сделали со своим процессором аннотаций, вы даже не сможете увидеть источник геттеров и сеттеров. чтобы исправить ошибки. Инструменты статического анализа сообщат вам, что атрибут никогда не используется и т. д.

Я согласен с общим мнением - просто сгенерируйте их в исходном файле, используя методы, которые дает вам каждая IDE. Это занимает едва ли больше времени, чем написание аннотаций, и это понятно каждому разработчику и каждому инструменту. У Java нет свойств — забудь об этом. :-)

person Andrzej Doyle    schedule 13.07.2010
comment
Я согласен, либо переключайте языки (Scala довольно крутая) и таким образом облегчайте жизнь, либо переключайтесь на лучшую IDE и дайте ей заполнить шаблон. Возможно, есть что-то еще для вашего требования, например, вы ДОЛЖНЫ генерировать исходный код Java, и, возможно, вы получаете исходный код в указанном формате? - person Java Drinker; 13.07.2010
comment
Я согласен, что дело в том, что у Java нет свойств. Спасибо за новое предложение, я не знал. Я поищу, как правильно обработать файл .class вместо файла .java. - person cibercitizen1; 13.07.2010

Это звучит как много работы только для создания методов получения и установки. Почему бы просто не использовать затмевает генераторы геттеров и сеттеров:

создать скриншот геттеров и сеттеров
(источник: eclipse-blog.org)

person krock    schedule 13.07.2010
comment
Я не использую eclipse :-( Я думаю, вы пропустили требование @Get @Set в моем вопросе. - person cibercitizen1; 13.07.2010
comment
Рассмотрите возможность использования IDE и избегайте всевозможных шаманств в процессе сборки. Когда-нибудь ты это оценишь. - person Thorbjørn Ravn Andersen; 13.07.2010
comment
Спасибо. Но что, когда вы меняете IDE? Я использую большую часть времени vi. В любом случае, я предпочитаю что-то независимое от редактора. - person cibercitizen1; 13.07.2010
comment
Да, я знаю, что это действительно поздний комментарий, но я думаю, что лучший способ — написать несколько сценариев/команд vim, которые выполняют генерацию кода такого рода. - person smelm; 15.01.2020

На практике я обычно использую подход 3 - я просто кодирую поля и использую eclipse IDE для автоматического создания методов получения и установки. (netbeans и IntelliJ должны иметь схожие функции)

С помощью инструментов автогенерации среды IDE вы даже можете определить видимость сгенерированных методов получения/установки (возможно, вы захотите ограничить видимость методов установки закрытыми) или отредактировать шаблон, если вам нужен дополнительный код для тела метода.

person Andreas Dolk    schedule 13.07.2010
comment
Я не использую eclipse :-( Я думаю, вы пропустили требование @Get @Set в моем вопросе. - person cibercitizen1; 13.07.2010
comment
@cibercitzen1 - да, я пропустил их, потому что вы просто не сказали, что @Get и @Set являются сильными требованиями. Но почему бы вам не использовать IDE, например eclipse, netbeans, JDeveloper, IntelliJ, ...? - person Andreas Dolk; 13.07.2010
comment
Обычно я использую vi или emacs. Но главная причина в том, что я хочу что-то независимое от редактора. - person cibercitizen1; 13.07.2010

  • а) Вы можете использовать язык JVM (совместимый с Java), который поддерживает это
  • б) Я бы написал это на Scala

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

person Landei    schedule 13.07.2010
comment
Прикомандирован. Посмотрите на Scala, он достаточно похож на Java, так что вы не будете чувствовать себя потерянным, но он избавляет (среди прочего) от необходимости явно кодировать геттеры и сеттеры. СМЕРТЬ БОЙЛЕРУ! Ммм, простите мой революционный энтузиазм. - person Carl Smotricz; 13.07.2010
comment
@cibercitizen1 - это зависит от того, на какой уровень вы смотрите. Это не исходный код Java, а классы Java. Вы можете вызывать класс, написанный на Scala, из класса, написанного на Java (и наоборот), так же естественно, как и нативный класс. Единственная разница в том, что Scala позволяет вам (но не принуждает) использовать другой синтаксис, который именно то, что вам нужно в вашем вопросе. - person Andrzej Doyle; 13.07.2010
comment
Ответы типа «Использовать другой язык программирования» обычно заслуживают отрицательного голоса... Кроме того: ДА ЗДРАВСТВУЕТ БОЙЛЕРПЛЕЙТ - person Andreas Dolk; 13.07.2010
comment
@Andreas_D: Обычно вы правы, но в подобных случаях, когда TO пытается эмулировать функцию, которая присутствует в другом языке (который даже совместим с байтовым кодом), следует разрешить упомянуть альтернативу, особенно когда все другие варианты уродливое, сложное или опасное. - person Landei; 28.04.2011
comment
@Landei (я не минусовал, но вчера тоже получил минус) - person Andreas Dolk; 28.04.2011

Project Lombok — это именно то, что вам нужно, хотя реализация отличается.

person Nakedible    schedule 27.04.2011

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

Итак, вы бы указали что-то вроде

открытый интерфейс Bean { public int getX(); общественный недействительный setX (целое значение); }

и попросите библиотеку создать экземпляр типа для этого (и, возможно, удобные методы для создания экземпляров типа). При необходимости аннотации можно использовать для дальнейшей настройки, но для bean-компонентов стиля get/set это не так.

Это отличается от вашего (2), который не будет работать как есть, если я что-то не упустил: дело в том, что у вас должны быть методы, доступные во время компиляции. И это то, что может решить использование интерфейсов. Потребуется генерация кода, но ее можно будет автоматизировать.

Я ожидаю, что такие библиотеки существуют, но если нет, то написание универсальной должно быть вполне выполнимо с использованием библиотек для генерации байтового кода (asm, cglib, janino, javassist и т. д.).

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

... и вполне может быть, что с помощью IDE будет проще всего решить конкретный случай, который у вас есть, каким бы он ни был. :-)

person StaxMan    schedule 13.07.2010