Преодолеть стирание типов в Java

У меня есть клиентский класс, который я не могу изменить.

List<Integer> list1= Arrays.asList(1,2,3);
System.out.println("Total sum is:"+sum(list1));
printlist(list1);
List<Double> list2=Arrays.asList(1.0,2.0,3.0);
System.out.println("Total sum is:"+sum(list2));
printlist(list2);

У меня здесь есть бизнес-логика

private static Object sum(List<? extends Number> list) {
    double sum = 0;
    for (Number i: list) {
        sum+=i.doubleValue();
    }     
    return sum;
}

Поэтому я хочу вернуть 6 для целого числа и 6.0 для двойного. Как я могу это сделать? Я думаю о приведении суммы как int или double в зависимости от типа, но из-за стирания типа вся информация теряется. Кто-нибудь может мне помочь?

Что, если это смесь Integer и Double?

shmosel 17.07.2018 06:03

Сейчас я не проверяю это условие. Я просто пытаюсь понять дженерики. Я новичок в дженериках

Harshal 17.07.2018 06:06

Нет другого способа узнать, что это за список, кроме как проверить его содержимое.

shmosel 17.07.2018 06:14

Так вы можете изменить метод «бизнес-логики»?

daniu 17.07.2018 06:17

вы можете использовать переопределение, даже java делает это

emotionlessbananas 17.07.2018 06:23

или посмотрите следующее: stackoverflow.com/questions/1759549/…

emotionlessbananas 17.07.2018 06:24
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
242
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Используйте instanceof

     if ( i instanceof Double) {
       System.out.println("param is a Double");
     }
     else if ( i instanceof Integer) {
       System.out.println("param is an Integer");
    }
Ответ принят как подходящий

Объекты в списке все еще имеют информацию о типе, связанную с ними во время выполнения. Единственные стертые типы - это типы дженериков (например, List в вашем примере). Дженерики проверяются во время компиляции, но не поддерживаются в сгенерированном байт-коде. Это означает, что вы можете использовать instanceof для проверки содержание коллекции:

private static Object sum(List<? extends Number> list) {
    Integer integerSum = 0;
    Double doubleSum = 0.0;
    boolean hasDouble = false;
    for (Number i: list) {
        if (i instanceof Integer) {
            integerSum += i.intValue();
        } else {
            doubleSum += i.doubleValue();
            hasDouble = true;
        }
    }
    if (hasDouble)
        return doubleSum + integerSum;
    return integerSum;
}

Код имеет некоторые особенности для обработки смешанных списков и некорректно обрабатывает Long, Short, Byte и т. д.

Конструктор Double вызывать не нужно. Просто верните doubleSum + integerSum.

shmosel 17.07.2018 06:36

Вы можете использовать double, чтобы суммировать все значения и привести его в конце.

Peter Lawrey 17.07.2018 07:43

Опасно предполагать, что экземпляр подкласса Number может быть представлен с помощью double. Чтобы сделать это безопасно, вам нужно проверить все возможные типы.

@SuppressWarnings("unchecked")
private static <T extends Number> T sum(List<T> list) {
    Objects.requireNonNull(list);

    if (list.isEmpty() || list.contains(null))
        throw new IllegalArgumentException();

    Class<T> clazz = (Class<T>) list.get(0).getClass();

    if (clazz == Integer.class) {
        return (T) (Integer) list.stream().mapToInt(i -> (Integer) i).sum();
    }
    else if (clazz == Double.class) {
        return (T) (Double) list.stream().mapToDouble(i -> (Double) i).sum();
    }
    /* And other Number subclass types */

    // Not possible if all types covered
    throw new IllegalStateException();
}

Здесь - это вопрос / ответ, связанный с этим.

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