Дженерики Java и числа

Сценарий, который я представляю: маршрут был протестирован методом GET (потому что не было аргумента methods), и все было хорошо. Был добавлен аргумент methods, чтобы можно было проверить POST, и он «перестал работать». Но он действительно не перестал работать, он просто не создан для обработки запроса POST.

Из фляги документа по запросу два существенных атрибута:

форма

MultiDict с проанализированные данные формы из запросов POST или PUT. Имейте в виду, что загрузка файлов здесь не заканчивается, а указывается в атрибуте files.

args

MultiDict с разобранным содержимым строки запроса. (Часть в URL после знака вопроса).

blockquote>

Таким образом, запрос GET будет «заполняться» args, а запрос POST - form. Имя пользователя будет None из этой строки Username = (request.args.get("Username")) по запросу POST.

Какой метод можно определить, запросив атрибут метода объекта запроса.

метод

Текущий метод запроса (POST, GET и т. д.)

blockquote>

18
задан Scott Lemke 18 May 2009 в 14:02
поделиться

11 ответов

Массивы и универсальные шаблоны не хорошо взаимодействуют вместе:

«Массивы ковариантны, что означает, что массив ссылок на супертипы является супертипом массива ссылок на подтипы. . То есть Object [] является супертипом String [] , и к массиву строк можно получить доступ через ссылочную переменную типа Object [] ».

см. Часто задаваемые вопросы по Java Generics :

8
ответ дан 30 November 2019 в 08:04
поделиться

Если вы действительно хотите использовать дженерики, вы можете сделать что-то вроде этого

private <T extends Number> T[][] zeroMatrix(int row, int col, Class<T> clazz) throws InstantiationException, IllegalAccessException,
        IllegalArgumentException, InvocationTargetException
{
    T[][] retVal = (T[][]) Array.newInstance(clazz, new int[] { row, col });
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            Constructor<T> c = clazz.getDeclaredConstructors()[0];
            retVal[i][j] = c.newInstance("0");
        }
    }

    return retVal;
}

Пример:

zeroMatrix(12, 12, Integer.class);
1
ответ дан 30 November 2019 в 08:04
поделиться
<T extends Number> T[][] zeroMatrix(Class<? extends Number> of, int row, int col) {
    T[][] matrix = (T[][]) java.lang.reflect.Array.newInstance(of, row, col);
    T zero = (T) of.getConstructor(String.class).newInstance("0");
    // not handling exception      

    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; 
            matrix[i][j] = zero;
        }
    }

    return matrix;
}

использование:

    BigInteger[][] bigIntegerMatrix = zeroMatrix(BigInteger.class, 3, 3);
    Integer[][] integerMatrix = zeroMatrix(Integer.class, 3, 3);
    Float[][] floatMatrix = zeroMatrix(Float.class, 3, 3);
    String[][] error = zeroMatrix(String.class, 3, 3); // <--- compile time error
    System.out.println(Arrays.deepToString(bigIntegerMatrix));
    System.out.println(Arrays.deepToString(integerMatrix));
    System.out.println(Arrays.deepToString(floatMatrix));

EDIT

общая матрица:

public static <T> T[][] fillMatrix(Object fill, int row, int col) {
    T[][] matrix = (T[][]) Array.newInstance(fill.getClass(), row, col);

    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            matrix[i][j] = (T) fill;
        }
    }

    return matrix;
}    

Integer[][] zeroMatrix = fillMatrix(0, 3, 3); // a zero-filled 3x3 matrix
String[][] stringMatrix = fillMatrix("B", 2, 2); // a B-filled 2x2 matrix
12
ответ дан 30 November 2019 в 08:04
поделиться

Вы должны учитывать, что обобщенные шаблоны используются только во время компиляции для проверки безопасности типов. Эта информация теряется во время выполнения, поэтому вы не можете использовать автоматическую упаковку для retVal [i] [j] = 0; поскольку Java не может автоматически вводить в поле тип Number или Object.

Если вы передадите значение, которое хотите установить, оно будет работать. Вот краткий пример:

private <T> T[][] fillMatrix(int row, int col, T value) {
    T[][] retVal = (T[][])new Object[row][col];
    for(int i = 0; i < row; i++) {
       for(int j = 0; j < col; j++) {
          retVal[i][j] = value;
       }
    }
    return retVal;
}

Между прочим, for (int i = row; i

редактировать: Вы не сможете преобразовать результат к чему-то другому, кроме Object [] [], потому что это фактический тип массива.

1
ответ дан 30 November 2019 в 08:04
поделиться

он должен быть нулевым вместо нуля.

Если вы действительно хотите поместить туда эквивалент 0 для объекта T, вам нужно будет предоставить фабрику T. Примерно так:

interface Factory<T> {
   T getZero();     
}

и вы должны сделать этот метод следующим образом:

private <T> T[][] zeroMatrix(int row, int col, Factory<T> factory) {
    T[][] retVal = (T[][])new Object[row][col];
    for(int i = row; i < row; i++) {
        for(int j = col; j < col; j++) {
            retVal[i][j] = factory.getZero();
        }
    }

    return retVal;
}

У вас также должен быть правильные реализации для фабрики:

 class IntegerFactory implements Factory<Integer> {
    Integer getZero() {
       return new Integer(0);
    }
}

Обычно вы помещаете getMatrix (int row, int column) в реализацию фабрики, чтобы фактически вернуть правильный типизированный массив.

3
ответ дан 30 November 2019 в 08:04
поделиться

Я думаю, вы проиграли битву. Даже если вы решите это, как вы планируете решать сложение, вычитание и т. Д.? Числовой класс не очень полезный суперкласс, и почти единственный полезный метод - это doubleValue ().

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

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

Другой очевидный вариант - оставить массив с нулевую инициализацию, а затем измените свой другой код так, чтобы null обрабатывался как ноль.

1
ответ дан 30 November 2019 в 08:04
поделиться

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

1
ответ дан 30 November 2019 в 08:04
поделиться

Обобщения и массивы не очень хорошо совпадают. Создание универсального массива не допускается, так как это небезопасно. Это проистекает из того факта, что если Sub является подтипом Super, то Sub [] является подтипом Super [], что не относится к универсальным типам; для любых двух различных типов Type1 и Type2 List не является ни подтипом, ни надтипом List. (Эффективная Java освещает это в главе 5, пункт 25).

1
ответ дан 30 November 2019 в 08:04
поделиться

В Java тип стирается во время выполнения, поэтому вам нужно передать другой аргумент, чтобы получить тип во время выполнения.

Это может быть либо значение для инициализации массивов, либо используемый класс.

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

Затем вы можете использовать java.util.Arrays. fill для заполнения массива:

private static HashMap<Class<?>, Object> ZEROS = new HashMap<Class<?>,Object>();

static {
    ZEROS.put( Integer.class, Integer.valueOf(0) );
    ...
}

private static <T extends Number> T[][] zeroMatrix ( Class<T> type, int rows, int cols ) {
    @SuppressWarnings("unchecked")
    T[][]   matrix  = (T[][]) java.lang.reflect.Array.newInstance(type, rows, cols);
    Object  zero    = ZEROS.get(type);

    for ( T[] row : matrix ) 
        java.util.Arrays.fill(row,zero);

    return matrix;
}

Integer[][] matrix = zeroMatrix (Integer.class, 10, 10);

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

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

2
ответ дан 30 November 2019 в 08:04
поделиться

Использование стирания в Java для реализации универсальных типов означает, что у вас возникнут проблемы с новым универсальным типом.

Как насчет использования null для представления 0

retVal[i][j] = null;

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

-1
ответ дан 30 November 2019 в 08:04
поделиться

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

1
ответ дан 30 November 2019 в 08:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: