方法代码Scala中的语言特性是如何实现的(2)
首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责
上篇博文的末尾留了三个问题,现在自问自答一下。
在Scala中被声明为val的v4为什么在反编译的Java中不是final的呢?
在方法中声明局部变量时,如果用Scala的val关键字(或者是Java中的final)来修饰变量,则代表着此变量在赋过初始值以后不可以再被重新赋值。这个val或者final只是给编译器用的,编译器如果发明你给此变量重新赋值会抛出错误。
而bytecode不具备抒发一个局部变量是immutable的能力,也就是说对于JVM来说,不存在不可变的局部变量这个概念。所以v4在反编译以后,就和普通的局部变量无异了。
在Scala中被声明为val的v2为什么在反编译的C#中不是readonly的呢?
这是个挺tricky的问题,我试着解释一下。Scala .NET是基于IKVM实现的,IKVM可以把Java bytecode翻译为CIL。 所以Scala编译为CIL的进程实际是这样的:
Scala —–Scala编译器—–> bytecode —–IKVM—–> CIL
Scala编译器编译出的bytecode实际是用final修饰了v2的,但是bytecode中的final和CIL中的initonly(对应C#的readonly)是不一样的。
Java中,final实例变量定义的时候,可以先声明,而不给初值,然后我们可以在任何一个方法中给它赋初值。这提供了更大的灵活性,一个Java类中的final成员可以依对象而不同,却坚持其immutable的特征。
而CIL的initonly则要严格一点,CLI标准(ECMA-334)这样描述:
initonly marks fields which are constant after they are initialized. These fields shall only be mutated inside a constructor. If the field is a static field, then it shall be mutated only inside the type initializer of the type in which it was declared. If it is an instance field, then it shall be mutated only in one of the instance constructors of the type in which it was defined. It shall not be mutated in any other method or in any other constructor, including constructors of derived classes.
可见,一个initonly的成员,不是随意在哪儿都可以赋初值的。由于这点不同IKVM就没有直接把final翻译成initonly。如果想让v2在C#代码中变成readonly的,可以给IKVM加上strictfinalfieldsemantics这个参数。
为什么反编译出来的C#代码中的实例级公然方法都是标有override的呢?
这个问题还没搞明确。
但是有个有趣的景象,如果用Scala .NET来编译Scala源码,编译出的实例级方法都是标有override的;而如果先把Scala代码编译为.class然后再用IKVM把.class文件转换为CIL的话,方法则是标有virtual的。我猜这可能和Java中的方法默许是可以被overirde的有关。
上面开始正文,前面填坑用了不少篇幅,所以这次只分析一个语言特性:Scala中的constructor。
Constructor
Scala中可以在声明class的同时声明一个constructor,比如这样:
构造函数接收两个参数x和y,然后把x和y拼在一起打印出来。反编译为Java:
可以发明编译器给标为val的x生成了一个getter,很便利的语法糖。而直接写在类内的打印语句则被放到了构造函数内。上面是反编译为C#的代码:
和Java代码基本无异。比拟一下,Scala用3行代码抒发的含意,Java和C#要用14行才行。
现在加一个重载的构造函数:
这个构造函数给了y一个默许值“hello”。反编译为Java:
对应的C#代码:
构造函数重载这个特性就显得平淡无奇了,不过还是比拟一下行数。定义两个构造函数,打印出构造函数的参数,声明一个getter,这三件事Scala只用7行代码就完成了,Java和C#都需要将近20行。
文章结束给大家分享下程序员的一些笑话语录: 小沈阳版程序员~~~ \n程序员其实可痛苦的了......需求一做一改,一个月就过去了;嚎~ \n需求再一改一调,一季度就过去了;嚎~ \n程序员最痛苦的事儿是啥,知道不?就是,程序没做完,需求又改了; \n程序员最最痛苦的事儿是啥,知道不? 就是,系统好不容易做完了,方案全改了; \n程序员最最最痛苦的事儿是啥,知道不? 就是,系统做完了,狗日的客户跑了; \n程序员最最最最最痛苦的事儿是啥,知道不? 就是,狗日的客户又回来了,程序给删没了!