嵌套BiFunction的深度(或限制,如果有的话)是多少

我一直在玩BiFunctionjava.util.function )。 我举了一些例子,我有一个问题。

是否可以使用BiFunction嵌套操作的次数有限制? 是否像想要的那样多次嵌套假设的add(a, b)方法一样简单?

例如三个嵌套的theFunction.apply()

 public static int methodContainingMethod (int a, int b, int c, BiFunction theFunction) { return theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c); } 

四个嵌套theFunction.apply()

 return theFunction.apply(theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c),c); 

嵌套的数量可以继续,我测试嵌套function超过十次。

我没有确切要求需要多少嵌套……但我很好奇这样可以做多少嵌套?

首先,这并不是以任何方式特定于BiFunction 。 所以你基本上都在问,嵌套方法调用有多深,简单的答案是Java编程语言本身没有指定限制。

存在可能限制数量的技术限制,但这些是技术限制,而不是通过规范限制。 当技术发展而不改变规范时,它们可能会被解除。

正如Alain O’Dea所解释的 ,如果最后一条指令应该被exception处理程序覆盖,则方法的代码大小限制为65535字节或65534字节。 此代码大小支持的嵌套方法调用量取决于某些因素。 例如,您正在使用interface和接口方法调用比具体类方法调用使用更多字节(调用BiFunction指令),此外,您使用BiFunction而不是直接的IntBinaryOperator因此每次调用都涉及装箱需要额外代码的int值。

但无论如何,还有另一个技术限制,即编译器实现。 当尝试使用更高的嵌套计数编译您的示例时, javac从以1500嵌套调用的stackoverflow结束的命令行运行,而Netbeans(使用与javac相同的编译器代码)设法在IDE开始展示之前编译2000嵌套调用奇怪的行为(我猜,它不能很好地处理编译器/语法高亮显示器的堆栈溢出)。

这表明IDE在表达式被解析之前具有更高的堆栈大小或环境设置中的其他差异影响了初始堆栈深度。 这导致了在实践中没有硬性限制的结论。 您可能能够编写一个编译器能够编译而没有问题的代码,而另一个编译器可以解决这个问题。

毕竟,相当于你问题的代码可以写成:

 public static int methodContainingMethod( int a, int b, int c, BiFunction theFunction) { int value = theFunction.apply(a, b); for(int i=0; i 

虽然我认为,你的想法更像是:

 public static int methodContainingMethod( IntBinaryOperator theFunction, int first, int second, int... rest) { int value = theFunction.applyAsInt(first, second); for(int next: rest) value=theFunction.applyAsInt(value, next); return value; } 

要么

 public static OptionalInt methodContainingMethod( IntBinaryOperator theFunction, int... arguments) { return IntStream.of(arguments).reduce(theFunction); } 

我不知道对此有固有的表达式限制,但实际上它将受到65534字节的JVM方法大小限制:

end_pc是独占的这一事实是Java虚拟机设计中的历史错误:如果方法的Java虚拟机代码长度正好为65535字节,并且以1字节长的指令结束,则该指令无法受到保护由exception处理程序。 编译器编写器可以通过将生成的Java虚拟机代码的最大大小限制为任何方法,实例初始化方法或静态初始化程序(任何代码数组的大小)到65534字节来解决此错误。

资料来源: https : //docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3