Создать массив определенного типа в зависимости от условия - PullRequest
2 голосов
/ 08 марта 2019

У меня есть регистр переключения для типа enum, в зависимости от того, какой массив я создаю. Похоже:

switch (type) {
    case BOOLEAN:
        Boolean[] booleans = new Boolean[];
    case STRING:
        String[] strings = new String[];
}

Интересно, можно ли извлечь его каким-нибудь методом, чтобы он работал так:

ArrayWrapper arrayWrapper = // some logic for which I am looking for

и затем у меня есть универсальный метод, который принимает любой тип массива, и я хотел бы вызвать его как method(arrayWrapper.getArray()); и он будет приведен к конкретному типу и обработан процессором определенного типа?

Ответы [ 3 ]

2 голосов
/ 08 марта 2019

Java Generics в сочетании с Reflection API можно использовать для получения экземпляра T[]:

@SuppressWarnings("unchecked")
public static <T> T[] createArrayInstance(Class<T> clazz, int size) {
    return (T[])Array.newInstance(clazz, size);
}

Если вы хотите сохранитьпо любой причине значение в результирующем массиве:

@SuppressWarnings("unchecked")
public static <T> T[] createArrayInstance(T obj) {
    T[] a = (T[])Array.newInstance(obj.getClass(), 1);//or whatever size you want
    a[0] = obj;
    return a;
}

См. также: Как создать универсальный массив в Java?

2 голосов
/ 08 марта 2019

Класс java.lang.reflect.Array предоставляет функциональные возможности для работы с массивами любого типа, не зная, какой это тип.

Используя этот класс, вы можете написать код, подобный этому:

public void example(Class<?> elemType) {
    Object[] arr = (Object[]) Array.newInstance(elemType, 10);

    // Do something with the array
}

(Не приводите к Object[], если вы хотите работать с массивами примитивных типов.)

Array является частью системы отражения. Это означает, что вам придется использовать Class объекты для типов элементов и, вероятно, иметь переменные типа Object для ссылки на значения элементов.

0 голосов
/ 08 марта 2019

Одним из возможных способов было бы связать тип элемента массива с параметром универсального типа и связать процессор и массив на раннем этапе:

public class ArrayProcessingWrapper<T> {
  private final T[] array;
  private final ArrayProcessor<T> processor;

  public ArrayProcessingWrapper(T[] array, ArrayProcessor<T> processor) {
    super();
    this.array = array;
    this.processor = processor;
  }

  public void processArray() {
    this.processor.process(this.array);
  }

}

Другим способом может быть использование функций

public abstract class Processor<T> {
  private final Supplier<T[]> arraySupplier;

  public Processor(final Supplier<T[]> arraySupplier) {
    super();
    this.arraySupplier = arraySupplier;
  }

  public T[] createArray() {
    return this.arraySupplier.get();
  }

  public void processNewArray() {
    this.doProcess(this.createArray());
  }

  protected abstract void doProcess(T[] data);
}

public class BooleanProcessor extends Processor<Boolean> {
  public BooleanProcessor(Supplier<Boolean[]> arraySupplier) {
    super(arraySupplier);
  }

  @Override
  protected void doProcess(Boolean[] data) {
    // Do fancy boolean stuff...
  }
}

Но взгляните также на Iterable<E> и / или Collection<E> (из которых ArrayList<E> - это то, что ведет себя как массив) вместо массивов.

Для меня кажется недостатком дизайна, если вам нужно использовать другую логику («процессоры») в зависимости от типа (времени выполнения) массива.

...