Проблема дублирования кода метода Java Generics относительно примитивных массивов

1

Поэтому я работаю над реализацией класса Grid для небольшой библиотеки личных утилит. После большой работы я убираю класс Grid и добавляю некоторые функции. Одним из ключевых компонентов, которые я хочу использовать с моим классом Grid, является возможность взять один, 2D-массив любого заданного типа в качестве аргумента конструктору.

Это работало нормально, пока я не понял, что я не могу скомпилировать код, который пытается передать в любой массив примитивов конструктору. Поскольку autoboxing не происходит на примитивных массивах, это представляет проблему дизайна для меня в виде повторного использования кода. Метод инициализации Grid тот же, независимо от типа переданного массива, даже если они являются примитивами, но, похоже, мне нужно написать отдельный конструктор для всех типов примитивов. Который оставляет меня с 9 различными конструкторами, предполагая, что я просто использую свой базовый конструктор (и я планировал иметь конструкторы с разными аргументами для таких вещей, как параметры сетки).

Правильно ли я полагаю, что избежать всего этого дублирования кода невозможно?

  • 2
    Да, ты прав. Сожалею.
  • 0
    Я запутался в том, что вы имеете в виду, что autoboxing doesn't happen on primitive arrays ; любой массив является объектом и может использоваться для универсального типа. Не могли бы вы показать свой код? Я не уверен, правильно ли я вас понимаю
Показать ещё 11 комментариев
Теги:
arrays
constructor
code-duplication

1 ответ

4
Лучший ответ

Вы можете избежать (большей части) дублирования, используя класс Array. Но это не очень хорошо: ваш параметр конструктора должен иметь тип Object, и вам нужно просто доверять своему вызывающему, чтобы передать фактический массив, а не Socket или Properties.

Например, вы можете сделать свой собственный бокс следующим образом:

<T> public T[][] boxArray(Class<T> clazz, Object array) {
    int height = Array.getLength(array);
    int width = height == 0 ? 0 : Array.getLength(Array.get(array, 0));
    T[][] result = (T[][]) Array.newInstance(clazz, height, width);
    for(int i = 0; i < height; i ++) {
        Object a = Array.get(array, i);
        for(int j = 0; j < width; j++) {
            result[i][j] = (T) Array.get(a, j); 
        }
    }
    return result;
}
  • 1
    Я понятия не имел, Array.get существует. Я бы не рекомендовал ОП на самом деле делать это (его класс должен быть явно общим), но +1 за изобретательность этого.
  • 0
    Это может работать на данный момент. Спасибо! Но как только я выпущу его для более широкой аудитории (как только я открою библиотеку с открытым исходным кодом), мне придется переключиться обратно на несколько конструкторов. Для открытого проекта я возьму дублирование кода меньшего из двух зол, когда речь заходит о безопасности типов. Однако для личных проектов это может сработать.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню