Spring 为什么traits中的具体函数实现编译成Scala 2.9.x中的桥接方法,而不是2.8.x中的桥接方法?
在2.9.0之前的Scala版本中,traits中的具体函数实现被编译为普通方法。从2.9.x开始,它们被编译为桥接方法。我试图找到这一变化背后的原因,因为它对许多流行Java框架(如Spring和Jersey)的用户产生了负面影响 考虑以下Scala代码:Spring 为什么traits中的具体函数实现编译成Scala 2.9.x中的桥接方法,而不是2.8.x中的桥接方法?,spring,scala,jvm,jersey,Spring,Scala,Jvm,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
trait Speaks {
def speak() = {
println("woof")
}
}
class Dog extends Speaks {
def wag() = {
println("wag wag")
}
}
当使用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
当使用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
有问题的部分是在speak()函数中添加了ACC_BRIDGE标志。像Jersey和Spring这样的框架在许多情况下故意不将桥接方法识别为其他问题的解决方法
那么,有人能解释或指出为什么Scala 2.9.x中会有这样的更改吗
接下来,有没有办法通过函数注释、编译器标志等来禁用此行为?好的,似乎没有解释原因,因为这不是有意的更改。请参阅此线程:
解决方案是使用最新的快照,或者,如果您在阅读本文时看到了未来,Scala 2.10是一个有趣的问题,但是,像许多这样的设计问题一样,最好[首先]在MLs上提问(然后在此处移植/聚焦)。例如,最终的SO问题可能是“如何让Spring识别…”