Getting java.lang.NoSuchMethodException in structural typing of AnyVal

前端 未结 2 1754
猫巷女王i
猫巷女王i 2021-01-15 06:19

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 h

相关标签:
2条回答
  • 2021-01-15 07:12

    I think the problem has nothing to do with AnyVal, AnyRef Or Any.

    addNumber1(new Foo("1")) 
    

    This works because you indeed defined a Foo class that provides an implementation of def +(s:Int):T.

    addNumber1(1)
    

    This doesn't work because Integer class doesn't provide it, as is mentioned in the exception:

    java.lang.NoSuchMethodException: java.lang.Integer.$plus(int)
    
    0 讨论(0)
  • 2021-01-15 07:14

    You run into an intersection of quite a few features:

    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).

    2. 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)
      
    3. 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.

    0 讨论(0)
提交回复
热议问题