Java Scala中的传递函数
由于Java 8,我可以通过Java Scala中的传递函数,java,scala,generics,java-8,Java,Scala,Generics,Java 8,由于Java 8,我可以通过 xyz.foreach(e -> System.out.println(e)); 我可以做到以下几点 xyz.foreach(System.out::println) 我已经了解了方法引用的工作原理,但问题如下: 错误:(16,63)对重载定义的引用不明确 类型为(源:IanesServer)字符串的对象IanesJsonHelper中的两个方法都是toJson 类型为(success:Boolean)字符串的对象IanesJsonHelper中的toJs
xyz.foreach(e -> System.out.println(e));
我可以做到以下几点
xyz.foreach(System.out::println)
我已经了解了方法引用的工作原理,但问题如下:
错误:(16,63)对重载定义的引用不明确
类型为(源:IanesServer)字符串的对象IanesJsonHelper中的两个方法都是toJson
类型为(success:Boolean)字符串的对象IanesJsonHelper中的toJson和方法
匹配预期类型函数[?,字符串]
val json = IanesJsonHelper.toJson(array,IanesJsonHelper.toJson _)
^
我有3个名为“toJSON”的函数
及
及
最后一个是正确的
我在上面的错误消息中调用的函数是:
def toJson[T](source: Array[T], toJson: Function[T, String]): String
以下是相关代码:
val array = new Array[IanesServer](1)
array(0) = new IanesServer(1, "http://localhost:4567/", "Test")
val json = IanesJsonHelper.toJson(array,IanesJsonHelper.toJson)
我不明白我的错误是什么:
IanesJsonHelper.toJson[IanesServer](array,IanesJsonHelper.toJson)
您希望编译器将toJson
推断为Function[IanesServer,String]
类型,因为source
是Array[IanerServer]
类型,因此T
等于IanesServer
不幸的是,scala编译器没有那么聪明。有两种方法可以帮助编译器:
IanesJsonHelper.toJson[IanesServer](数组,IanesJsonHelper.toJson)
def toJson[T](source: Array[T])(toJson: Function[T, String]): String
IanesJsonHelper.toJson(array)(IanesJsonHelper.toJson)
T
,编译器将对其余列表使用这些绑定
下面是另一个较短的示例:
// doesn't compile - the compiler doesn't realize `_` is an Int and therefore doesn't know about the `+` operator
def map[A, B](xs: List[A], f: A => B) = ???
map(List(1,2,3), _ + 1)
//compiles fine
def map[A, B](xs: List[A])(f: A => B) = ???
map(List(1,2,3))(_ + 1)
scala> def f[A](x: A, y: A): A = x
f: [A](x: A, y: A)A
scala> f(Some(1), None)
res0: Option[Int] = Some(1)
这种行为可能看起来很不幸,但这是有原因的 Scala不同于Java或C#,它使用函数参数列表中的所有参数来计算它们的LUB(最小上界),并使用它来推断函数的泛型类型参数 例如:
// doesn't compile - the compiler doesn't realize `_` is an Int and therefore doesn't know about the `+` operator
def map[A, B](xs: List[A], f: A => B) = ???
map(List(1,2,3), _ + 1)
//compiles fine
def map[A, B](xs: List[A])(f: A => B) = ???
map(List(1,2,3))(_ + 1)
scala> def f[A](x: A, y: A): A = x
f: [A](x: A, y: A)A
scala> f(Some(1), None)
res0: Option[Int] = Some(1)
在这里,scala使用了两个参数(类型分别为Some[Int]
和None
)来推断A
(Option[Int]
-LUB)的类型。这就是scala需要您告诉它您所指的到JSON
的重载的原因
另一方面,C#
编译错误(第17行,第3列):无法从用法推断方法“Program.F(T,T)”的类型参数。请尝试显式指定类型参数
最后一点注意:LUBing非常棒,但也有它的缺点。这很糟糕,Scala编译器没有那么聪明。够了。问题是,(2)不起作用(IntelliJ抱怨说,没有方法具有这种siigneture)。我使用的是“IanesJsonHelper.toJson[IanesServer](数组,IanesJsonHelper.toJson)”现在。非常感谢!PS:感谢您多次编辑您的帖子:)有助于让事情变得更清楚(老实说,没有讽刺)@Reisi007我知道,对吗?这对我来说也很惊讶,尤其是来自C#的背景,在那里可以编译。尽管有这个小怪癖,我还是会选择scala的类型推断而不是C#的。我来自Java,一点问题都没有。。(我想,没有经过测试)。我刚刚习惯Scala。无论如何,谢谢你的快速回答。非常赞赏:D@Reisi007经过进一步思考,我意识到编译器的这种行为是有原因的。我已经更新了我的帖子,希望有帮助:)
// doesn't compile - the compiler doesn't realize `_` is an Int and therefore doesn't know about the `+` operator
def map[A, B](xs: List[A], f: A => B) = ???
map(List(1,2,3), _ + 1)
//compiles fine
def map[A, B](xs: List[A])(f: A => B) = ???
map(List(1,2,3))(_ + 1)
scala> def f[A](x: A, y: A): A = x
f: [A](x: A, y: A)A
scala> f(Some(1), None)
res0: Option[Int] = Some(1)