Create a zero value of a generic Number subclass

How can I generically create a zero of an arbitrary numeric type?

Here's a toy example: a function that converts a null number into zero.

static <T extends Number> T zeroIfNull(T value) {
    return value == null ? 0 : value;
}

This doesn't compile because the literal zero is of type int, and I need to convert that to type T.

Is it possible to do this at all?

14
задан kiamlaluno 23 August 2010 в 02:39
поделиться

6 ответов

Ноль даже не упоминается в классе Number . Если вы должны это сделать, и я предлагаю избегать null s, возможно:

public static <T> T coalesce(T a, T b) {
    return a==null ? b : a;
}

Вы также можете создать общий интерфейс для обработки чисел с функциями, которые имеют смысл для вашего кода:

interface NumberOps<T extends Number> {
    T zeroIfNull(T value);
}
2
ответ дан 1 December 2019 в 17:09
поделиться

Следующее - улучшение моего первого ответа.

import java . math . * ;
import java . util . * ;

class Numbers
{
    private static final Map<Class<? extends Number>,Object> zeroes = new HashMap<Class<? extends Number>,Object> ( ) ;

    static
    {
         zeroes . put ( Integer . class , new Integer ( 0 ) ) ;
         zeroes . put ( Double . class , new Double ( 0.0 ) ) ;
         zeroes . put ( BigInteger . class , BigInteger . ZERO ) ;
         // fill it up with all supported classes
    }

    public static < T extends Number > T zeroIfNull ( T number , Class<T> clazz ) throws IllegalArgumentException
    {
    if ( number == null ) // return zero (if we know what zero is)
        {
        if ( zeroes . containsKey ( clazz ) )
            {
            return ( clazz . cast ( zeroes . get ( clazz ) ) ) ;
            }
        throw new IllegalArgumentException ( "Unexpected Number Class " + clazz . getName ( ) + " with undefined zero value." ) ;
        }
    return number ;
    }
}
-2
ответ дан 1 December 2019 в 17:09
поделиться
import java . math . * ;

class Numbers
{
    public static < T extends Number > T zeroIfNull ( T number , Class<T> clazz ) throws IllegalArgumentException
    {
    if ( clazz == Integer . class )
        {
        return zeroIfNull ( number , clazz , 0 ) ;
        }
    else if ( clazz == Double . class )
        {
        return zeroIfNull ( number , clazz , 0 ) ;
        }
    else if ( clazz == BigInteger . class )
        {
        return zeroIfNull ( number , clazz , BigInteger . ZERO ) ;
        }
    // add a whole bunch more if statements
    throw new IllegalArgumentException ( "Unexpected Number Class " + clazz . getName ( ) + " with possibly undefined zero value." ) ;
    }

    private static < T extends Number > T zeroIfNull ( T number , Class<T> clazz , Object zero )
    {
    if ( number == null )
        {
        return ( clazz . cast ( zero ) ) ;
        }
    else
        {
        return ( number ) ;
        }
    }
}
-2
ответ дан 1 December 2019 в 17:09
поделиться

Возможно ли это вообще сделать?
Не совсем. Во-первых, когда значение равно null, как метод узнает, какую реализацию Number возвращать?

3
ответ дан 1 December 2019 в 17:09
поделиться

попробуйте:

   return value == null ? (T)Integer.valueOf(0) : value;
0
ответ дан 1 December 2019 в 17:09
поделиться

Не очень элегантно, но я думаю, что в большинстве подобных случаев мы можем сделать это:

static <T extends Number> T zeroIfNull(T value, Class<T> clazz) {...}

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

BigDecimal v = zeroIfNull(orignalVal, BigDecimal.class);
-1
ответ дан 1 December 2019 в 17:09
поделиться
Другие вопросы по тегам:

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