开发者学堂课程【Scala 核心编程-基础:Java 模拟 Scala 的运行机制】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8884
Java 模拟 Scala 的运行机制
目录
一、 反编译代码
二、 使用 Java 模拟 scala 运行机制代码
接下来通过模拟代码来查看 Scala 编译的执行过程。前面已经使用 ed 将流程展示完了,但是并没有写一段模拟代码,所以本节课将使用 java 写一段模拟代码来展示它是怎样运行的。
一、 反编译代码
这里以 TestScala 为例,代码如下:
package com. atguigu.chapter01
object Testscala {
def main(args: Array[String]): unit = {
println
(“hello,scala,idea…”)
}
}
运行结果:
D:\program\jdk8\bin\java…
hello, scala, idea…
Process finished with exit code 0
为什么运行出 hello, scala, idea 呢?写一段模拟代码:
新建一个 New Package 名为 test,打开反编译工具,找到
需要注意的是整个 scala 项目会默认放在,如若不知道放在哪可以右键项目找到 Show in Explorer,打开后就可以发现项目的路径是 C:\Users\Administrator\IdeaProjects\java0705scala\src\main\scala\com\atguigu\chapter01里。
那么使用反编译寻找:首先找到 C 盘下的用户;打开里面的 Administrator 文件;选择 IdeaProjects,这里面有很多项目文件夹,选择刚才所建的 java0705scala 文件;这里有3个文件夹:.idea、src、target。选择 src 文件, src 是源代码,源代码就是所写的那部分代码;如所写的 main 里的 scala 部分代码,继续往下路径就找到了。
但是这里需要找到 class 文件,则应该在 target 里寻找,发现这里已经有 TestScala.class 文件,将其打开,可以看到代码如下:
package com.atguigu.chapter01;
import scala.reflect.ScalaSignature;
@ScalaSignature(
b
ytes=”\006\001%:Q!\001\002\t\002$\t\021\002v3tiN\033\027\r
\
\1\013\005\r!\021!C2Icb$XM\035\0312\025\t)a!A\004bi\036,\03”)
public final class Testscala
{
public static void main(String[] paramArrayOfString)
{
Testscala..MODULE$ .main (pararArrayOfString) ;
}
}
二、 使用 Java 模拟 scala 运行机制代码
可以看到以上代码里有一个 Testscala,由于要模拟它所以创建与它一样的名字,则在 Idea 新建一个 javaClass,名称就为 Testscala。整体代码就显示出来了,这里直接将以上代码复制在其中,代码如下:
package com.atguigu.chaptero1.test;
public class Testscala {
public static void main(string[] paramArrayOfString) {
//Testscala..MODULE$.main(paramArrayOfString);
Testscala$.MODULE$
.
main(paramArrayOfString);
//调用 MODULE$静态函数,再调用 main 函数,paramArrayOfString是其参数。
}
}
这里会报错,是因为代码没有写全,则需要将 Testscala$里的代码复制过来,由于这段代码就已经是 java 代码了,所以复制过来就是反编译 java,将其整理之后代码如下:
final class Testscala$
{
public static final T
est
S
cala
$ MODULE$;
//补充类型
static
{
MODULE$ = new Testscala$();
//初始化
}
public void main(string[ ] args)
{
S
ystem
.out.println(“hello,scala
,
idea...”);
//这部分代码在调用时是 Scala 部分,这里不做使用,而是输出一句话。
}
/
/private Testscala$() {MODULE$ = this; }
}
反编译与实际代码是有区别的,因此在这里做了改进,以上这样就改写完了,可以看出和反编译之后的代码很相像。首先在 TestScala 里写了一个 Object 之后会生成两个 class,即上面代码中的 public class Testscala 与 final class Testscala$,TestScala 里代码如下:
package com.atguigu.chapter01
object TestScala {
def maih( args : Array[String]): unit = {
println(“hello,scala,idea...”)
}
}
真正的 main 入口是在 public class Testscala 代码里,但是实际的代码是在下面的 final class Testscala$代码里做了包装,可以理解为 scala 在运行时做了包装。至于做包装的原因由于太复杂这里只做简单解答:scala 是把一个类的静态和非静态分成两个部分,所以需要做包装;如若只有一个类则不会做包装。
所以这里写了一个 Object 就会生成两个值,写了一个主函数进来调用 Testscala$里的 MODULE$。思考在整个运行过程中的 MODULE$对象是否始终是同一个对象呢?也就是说在 scala 里写了一个 object 对象也就等价于 TestScala的一个静态对象而且是单例的,这个在之后会详细讲解。
总结:
只要以后看到有 object,应该有这样的认识:
1. object Testscala 对应的是一个 Testscala$的一个静态对象 MODULE$。
2. 在程序中,是一个单例。
运行,观察代码是否能够跑起来:
D:\program\jdks\bin\java...
hello,scala,idea...
Process finished with exit code 0
可以看到结果是一样的。简单来理解就是它做了一个包装,在调用时底层用了一个静态对象来调用主函数。
以上包装就讲解到这里。