在 AnyVal 的结构类型中获取 java.lang.NoSuchMethodException [英] Getting java.lang.NoSuchMethodException in structural typing of AnyVal
问题描述
我有以下代码段(我认为)在泛型类型 T
上定义了一个方法 addNumber1(x:T):T
,它是 AnyVal
并有一个方法 +(s:Int):T
.
I have the following snippet that (I think) defines a method addNumber1(x:T):T
on a generic type T
which is a subtype of AnyVal
and has a method +(s:Int):T
.
def addNumber1[T <: AnyVal {def +(s:Int):T}](x:T):T = {x + 1}
addNumber1(31) // compiles but throws exception
java.lang.NoSuchMethodException: java.lang.Integer.$plus(int)
at java.lang.Class.getMethod(Class.java:1786)
at .reflMethod$Method1(<console>:8)
at .addNumber1(<console>:8)
... 33 elided
我尝试添加 import scala.language.reflectiveCalls
来抑制功能警告,但仍然出现错误.
I tried adding import scala.language.reflectiveCalls
to suppress a feature warning but still get the error.
我可以在使用 AnyRef
或 Any
时使用它,如下所示:
I am able to use this when working with AnyRef
or Any
as below:
def addNumber1[T <: Any {def +(s:Int):T}](x:T):T = {x + 1}
class Foo(s:String) {def +(i:Int) = new Foo((s+1).toString)} // random code
class Bar(s:Foo) {def +(i:Int) = new Bar(new Foo(i.toString))} // random code
addNumber1(new Foo("1")) // works
addNumber1(new Bar(new Foo("1"))) // works
addNumber1(1) // compiles but gives exception
推荐答案
你遇到了很多功能的交集:
You run into an intersection of quite a few features:
就 Scala 编译器的初始阶段(包括类型检查)而言,
Int
确实有一个(重载的)+
方法.但是这个方法"在后面的阶段会被特别处理(Int
上的所有方法也是如此,因为它并不是真正的类).
So far as the initial stages of Scala compiler are concerned (including typechecking),
Int
does have an (overloaded)+
method. But this "method" is treated specially by the later stages (as are all methods onInt
, because it isn't really a class).
在 Scala 中定义的称为 +
的方法被转换为字节码中称为 $plus
的方法,因为 +
是不合法的那里的标识符.由于 +
上的 Int
是特殊的,如上所述,这不适用于它.由于结构类型是使用 Java 反射实现的,您的 addNumber1
看起来有点像
Methods called +
and defined in Scala are translated to methods called $plus
in bytecode, since +
is not a legal identifier there. Since +
on Int
is special, as mentioned above, this doesn't apply to it. Since the structural types are implemented using Java reflection, your addNumber1
looks somewhat like
def addNumber1(x: Object) = x.getClass.getMethod("$plus").invoke(x, 1)
要在 int
上调用 addNumber1
,必须先将它装箱为 Integer
,因为 int
代码> 不是一个对象.Integer
不是 Scala 类型,没有 $plus
方法.在 Scala 中,您可以编写类似 val x: Integer = ...;x + 1
,但这使用了 Java 反射不知道的隐式转换.
To call addNumber1
on an int
, it has to be boxed to Integer
first, because int
is not an object. Integer
, not being a Scala type, doesn't have a $plus
method. In Scala you can write something like val x: Integer = ...; x + 1
, but this uses an implicit conversion which Java reflection has no idea about.
这篇关于在 AnyVal 的结构类型中获取 java.lang.NoSuchMethodException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!