简体   繁体   English

什么是 C# default(T) 的 Java 等价物

[英]What is Java equivalent of C# default(T)

I'm currently working on generic Sum projection for one of my projects.我目前正在为我的一个项目进行通用 Sum 投影。 The code is like,代码就像,

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;
    }
}

However there is a little glitch here since I need to initialize the total (obviously to 0).但是这里有一个小故障,因为我需要初始化总数(显然是 0)。 But is there anyway to do it in java like in C# I could use default(U) .但是无论如何在Java中做它就像在C#中我可以使用default(U)

Java's equivalent to C#'s default(T) is null , which clearly would not work in your case, because you would get a NullPointerException the first time you tried to add something to your total. Java 相当于 C# 的default(T)null ,这显然不适用于您的情况,因为您第一次尝试将某些内容添加到总数时会得到 NullPointerException 。

In order to initialize your total you would need a factory method in java, but it still would not work, because:为了初始化您的总数,您需要在 Java 中使用工厂方法,但它仍然无法正常工作,因为:

  1. you cannot use += on generics in java.你不能在 java 中的泛型上使用+=
  2. java.lang.Number is immutable, so you cannot add anything to it. java.lang.Number是不可变的,因此您不能向其中添加任何内容。

You have two options.你有两个选择。

The massively overengineered approach:大规模过度设计的方法:

Define a new interface called, say, MyNumber which contains an add method, and write associated non-immutable numeric classes implementing this interface, so your code would then look like this:定义一个名为MyNumber的新接口,其中包含一个add方法,并编写相关的非不可变数字类来实现该接口,因此您的代码将如下所示:

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

(You would also need to write a factory so that you can create an instance to hold your total without knowing precisely what type it is.) (您还需要编写一个工厂,以便您可以创建一个实例来保存您的总数,而无需确切知道它是什么类型。)

The pragmatic approach:务实的方法:

Write cascaded if statements like this:编写像这样的级联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
}
...

Generics only exist for reference types anyway , so this would always be null . 无论如何泛型只存在于引用类型中,因此这将始终为null There also seems to be an implicit assumption that the + operator is defined for U - are you sure there aren't more constraints on what U can be?似乎还有一个隐含的假设,即 + 运算符是为U定义的 - 您确定对U可以是什么没有更多限制吗? Also have you looked at doing Stream.map followed by Stream.reduce ?你也看过做Stream.map然后是Stream.reduce吗? (I assume you are using Java 8 as you have Function ) (我假设您使用的是 Java 8,因为您有Function

EDIT I think what you are looking for is the monoid pattern.编辑我认为你正在寻找的是幺半群模式。 It doesn't exist in Java but you can define it yourself -它在 Java 中不存在,但您可以自己定义它-

interface Monoid<T>
{
    T getZero();
    T add(T left, T right);
}

And thus your example would become因此你的例子会变成

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));
}

but that would require changing the signature of eval , which might not be possible as I see it's annotated @Override .但这需要更改eval的签名,这可能是不可能的,因为我看到它被注释为@Override

This approach is extensible to Lists and Strings with Concatenation, Sets with union and Maps where the value is itself a monoid, "adding" all values of a given key, and functions under composition where the "zero" is the identity function.这种方法可以扩展到带有连接的列表和字符串、带有联合的集合和映射,其中值本身是一个幺半群,“添加”给定键的所有值,以及组合下的函数,其中“零”是恒等函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM