Автоматическая генерация неизменяемого класса и соответствующего класса построителя интерфейса Java

Какие инструменты или библиотеки существуют для Java, которые потребуют interface только с определениями методов доступа и автоматически генерировать неизменный класс объектов, а также класс "строитель" для поэтапного создания новых экземпляров или изменения существующих экземпляров путем создания новых?

Пример ввода:

public interface Car {
    String getModelName();
    int getWheelCount();
}

Пример вывода:

import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.NotThreadSafe;

@Immutable
public final class ImmutableCar implements Car {

    @NotThreadSafe
    public static final class Builder implements Car {

        private String modelName;
        private int wheelCount;

        public Builder() {
        }

        public Builder(final Car car) {
            modelName = car.getModelName();
            wheelCount = car.getWheelCount();
        }

        public ImmutableCar build() {
            return new ImmutableCar(wheelCount, modelName);
        }

        @Override
        public String getModelName() {
            return modelName;
        }

        @Override
        public int getWheelCount() {
            return wheelCount;
        }

        public void setModelName(final String modelName) {
            this.modelName = modelName;
        }

        public void setWheelCount(final int wheelCount) {
            this.wheelCount = wheelCount;
        }
    }

    private final String modelName;
    private final int wheelCount;

    public ImmutableCar(final int wheelCount, final String modelName) {
        this.wheelCount = wheelCount;
        this.modelName = modelName;
    }

    @Override
    public String getModelName() {
        return modelName;
    }

    @Override
    public int getWheelCount() {
        return wheelCount;
    }

}

5 ответов

Решение

Процессор аннотаций Immutables ( http://immutables.github.io/) точно соответствует вашим потребностям. Это полнофункциональный и очень настраиваемый (вы знаете все эти set против with против войн без префиксов, - используйте то, что вы предпочитаете). Он может генерировать неизменную реализацию со строителями для интерфейсов, абстрактных классов, аннотаций. Кроме того, он может генерировать компоновщики для вызова статических фабричных методов или конструкторов POJO и многих других вещей.

@Value.Immutable
public interface ValueObject {
  String name();
  List<Integer> counts();
  Optional<String> description();
}

// Compile using annotation processor and use it like this
ValueObject valueObject =
   ImmutableValueObject.builder()
      .name("My value")
      .addCounts(1)
      .addCounts(2)
      .build();

Google есть инструмент под названием AutoValue, который делает это, за исключением основанного на абстрактном базовом классе вместо интерфейса.

import com.google.auto.value.AutoValue;

class Example {
  @AutoValue
  abstract static class Animal {
    static Builder builder() {
      return new AutoValue_Example_Animal.Builder();
    }

    abstract String name();
    abstract int numberOfLegs();

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder name(String s);
      abstract Builder numberOfLegs(int n);
      abstract Animal build();
    }
  }
}

Другой подобный инструмент - Immutables; это, вероятно, ближе к вопросу, так как он использует интерфейс и генерирует неизменную реализацию и компоновщик.

Lombok позволяет код, подобный этому:

@lombok.Data
@lombok.Builder
public class ImmutableCar implements Car {
    private final @lombok.NonNull String modelName;
    private final @lombok.NonNull int wheelCount;
}

Аннотации lombok обрабатываются во время компиляции (JSR-269) для генерации полного класса. Также можно посмотреть на сгенерированный код с помощью "delomboking" через плагин Maven.

Я только что создал плагин затмения https://github.com/karajdaar/templator.

Он генерирует код на основе шаблонов Freemarker. Контекстом шаблона Freemarker является ICompilationUnit, который обеспечивает полный доступ к именованным классам и их информации. Мы используем его для генерации DAO для баз данных NoSQL, клиента джерси, тестов и т. Д.

Я думаю, что он может легко сделать то, что требуется здесь.

Посмотрите проект Eclipse Model2Text и его подпроекты, особенно Acceleo и Xpand. они обычно используются для генерации Java-кода на основе EMF для моделей EMF, но они также могут использоваться для генерации простых POJO.

однако эта функциональность не из коробки: вам нужно создать свой собственный генератор кода и шаблоны для него. см. учебник Accelelo.

РЕДАКТИРОВАТЬ:

еще одна идея - такая простая, что мне потребовался день, чтобы ее реализовать

Вы можете использовать Velocity, Freemarker или подобную библиотеку шаблонов (которые обычно используются для генерации HTML). хотя вам все равно нужно где-то создать модель, например, в файле.txt или.xml. Вот учебник по генерации кода Velocity.

Другие вопросы по тегам