为什么特性中的具体函数实现被编译为桥接Scala 2.9.x中的方法而不是2.8.x中的方法?

Jan*_*anx 11 spring jvm scala jersey

在2.9.0之前的Scala版本中,traits中的具体函数实现被编译为常规方法.从2.9.x开始,它们被编译为桥接方法.我试图找到这种变化背后的原因,因为它对许多流行的Java框架(如Spring和Jersey)的用户产生了负面影响.

请考虑以下Scala代码:

trait Speaks {
  def speak() = {
    println("woof")
  }
}

class Dog extends Speaks {
  def wag() = {
    println("wag wag")
  }
}
Run Code Online (Sandbox Code Playgroud)

当使用scalac版本2.8.1编译Dog类并使用javap进行反编译时,"speak"和"wag"函数的结果如下所示:

public void speak();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokestatic  #11                 // Method Speaks$class.speak:(LSpeaks;)V
         4: return        
      LineNumberTable:
        line 7: 0

public void wag();
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #18                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
         3: ldc           #20                 // String wag wag
         5: invokevirtual #24                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
         8: return        
      LineNumberTable:
        line 9: 0
Run Code Online (Sandbox Code Playgroud)

当使用scalac版本2.9.1编译Dog并再次反编译时,相同的两个函数看起来像:

public void speak();
  flags: ACC_PUBLIC, ACC_BRIDGE
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0       
       1: invokestatic  #11                 // Method Speaks$class.speak:(LSpeaks;)V
       4: return        
    LineNumberTable:
      line 7: 0

public void wag();
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=1, args_size=1
       0: getstatic     #18                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       3: ldc           #20                 // String wag wag
       5: invokevirtual #24                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
       8: return        
    LineNumberTable:
      line 9: 0
Run Code Online (Sandbox Code Playgroud)

有问题的部分是在speak()函数中添加了ACC_BRIDGE标志.像Jersey和Spring这样的框架在许多情况下故意不认识桥接方法作为其他问题的解决方法.

因此,任何人都可以解释或指出为什么在Scala 2.9.x中进行此更改的一个很好的解释?

作为后续,有没有办法通过函数注释,编译器标志等禁用此行为?

Jan*_*anx 7

好吧,听起来没有解释为什么,因为它不是故意改变.请参阅此主题:http: //groups.google.com/group/scala-language/browse_thread/thread/67f8884081d46912

解决方案是使用最新的快照,或者,如果您在阅读本文时未来已经到达,则使用Scala 2.10