在 AnyVal 的结构类型中获取 java.lang.NoSuchMethodException [英] Getting java.lang.NoSuchMethodException in structural typing of AnyVal

查看:37
本文介绍了在 AnyVal 的结构类型中获取 java.lang.NoSuchMethodException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码段(我认为)在泛型类型 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.

我可以在使用 AnyRefAny 时使用它,如下所示:

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:

  1. 就 Scala 编译器的初始阶段(包括类型检查)而言,Int 确实有一个(重载的)+ 方法.但是这个方法"在后面的阶段会被特别处理(Int 上的所有方法也是如此,因为它并不是真正的类).

  1. 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 on Int, 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屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆