什么是Java相当于C#的默认值(T)

Low*_*can 5 java generics

我正在为我的一个项目进行通用Sum投影.代码就像,

public class Sum<T,U extends Number> implements IProject<T,U,U>
{
    @Override
    public U eval(Iterable<T> tList, Function<T,U> property)
    {
        U total;
        for (T t : tList)
        {
            total += property.apply(t);
        }
        return total;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是这里有一点小问题,因为我需要初始化总数(显然为0).但是无论如何在java中我都可以使用它default(U).

Geo*_*mms 5

无论如何,泛型仅针对引用类型而存在,因此始终如此null。似乎还有一个隐含的假设,即 + 运算符的定义是为了U- 您确定没有更多的限制吗U?您还看过Stream.map随后做的事情Stream.reduce吗?(我假设您正在使用 Java 8 Function

编辑我认为你正在寻找的是幺半群模式。它在 Java 中不存在,但你可以自己定义它 -

interface Monoid<T>
{
    T getZero();
    T add(T left, T right);
}
Run Code Online (Sandbox Code Playgroud)

因此你的例子将变成

public U eval(Iterable<T> tList, Function<T,U> property, Monoid<U> m)
{
    U initial = m.getZero();
    return StreamSupport.stream(tList.spliterator(), false)
        .map(property)
        .reduce(initial, (uLeft, uRight) -> m.add(uLeft, uRight));
}
Run Code Online (Sandbox Code Playgroud)

但这需要更改 的签名eval,这可能是不可能的,因为我看到它被注释了@Override

这种方法可扩展到具有串联的列表和字符串、具有并集的集合和映射,其中值本身就是一个幺半群,“添加”给定键的所有值,以及组合下的函数,其中“零”是恒等函数。


Mik*_*kis 5

Java的等同于C#的default(T)null,这显然不会工作你的情况,因为你会得到一个NullPointerException你第一次尝试的东西添加到您的总.

为了初始化你的总数,你需要一个java的工厂方法,但它仍然无法工作,因为:

  1. 你不能+=在java中使用泛型.
  2. java.lang.Number 是不可变的,所以你不能添加任何东西.

你有两个选择.

大量过度设计的方法:

定义一个名为的新接口,例如,MyNumber它包含一个add方法,并编写实现此接口的相关非不可变数值类,因此您的代码将如下所示:

@Override
public <T extends MyNumber> T add( T total, Iterable<T> myNumbers )
{
    for( T myNumber : myNumbers )
        total.add( myNumber );
    return total;
}
Run Code Online (Sandbox Code Playgroud)

(您还需要编写一个工厂,以便您可以创建一个实例来保存您的总数,而无需确切知道它是什么类型.)

务实的方法:

写下这样的级联if语句:

if( number instanceof Integer )
{
    //declare int total
    //loop to sum integers
    //box the total into a Number
}
else if( number instanceof Long )
{
    //declare long total
    //loop to sum longs
    //box the total into a Number
}
...
Run Code Online (Sandbox Code Playgroud)