开发者学堂课程【Scala 核心编程-基础:Scala 快速入门】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8882
Scala 快速入门
目录
一、 案例
二、 步骤
三、 说明
四、 试验
一、 案例
需求说明:要求开发一个 Hello.scala 程序,可以输出“hello,世界!”[对 scala 程序基本结构说明]。
windows 下开发步骤[先使用 ed]
1. 可以直接使用文本开发工具[editplus]。
2. 将 Scala 代码编写到扩展名为 Hello.scala 的文件中。
[说明:比如将源码在目录 d:/scalademo 下]
3. 通过 scalac 命令对该 scala 文件进行编译,生成.class 文件。
[和 javac 类似]
4. 命令行下执行 scala Hello 就可以看到运行效果。
5. 注意:scala Hello.scala 命令可以直接运行 Hello.scala 程序。
[内部也会有编译和运行过程]
这里先使用 ed 开发,这样可以更加清楚的看到 scala 程序结构。
二、 步骤
这里先不使用集成工具,否则很难看到底层是怎样运行的。先在 D 盘 scalademo 文件夹里新建文本名为HelloScala,更改后缀名为 scala,为做对比则新建文本为 HelloJava.java。写 java 的代码如下:
public class HelloJava
{
public static void main(Stringargs) {
//写的是 public 函数
System.out.println(“hello,java!”)
; //注意不要忘记分号
}
}
打开 cmd.exe 输入以下命令查看是否运行:
D:\scalademo>javac HelloJava.java //使用 javac 进行编译
//编译完成后可在文件目录中得到一个 HelloJava.class 文件。
D:\scalademo>javac HelloJava //运行
hello,java! //输出 hello,java! 没有问题。
接下来写第二个文件:
打开 HelloScala.scala 文件编写代码,代码如下:
object HelloScala {
//1. def 表示是一个方法,这是一个关键字
//2. main 表示方法名字,表示程序入口
//3. args: Array[String]表示形参,scala 的特点是将参数名在前,类型后
//4. Array[String]表示类型一个数组
//5. Unit = 表示该函数的返回值为空
//6. println(“hello,scala!~~”)输出一句话
def main(args: Array[String]) : Unit = {
//def 是主函数,args 参数写前面,Array 类型为 String
println(“hello,scala!~~”)
//运行
}
}
开始编译:
D:\scalademo>scalac HelloScala.scala //编译完成后得到了两个文件:HelloScala$.class和HelloScala.class。这与它运行的原理有关,涉及到伴生内核、伴生对象,后面会做简单解释。
运行:
D
:\
scalademo>scala
Hello
S
cala
hello
,scala!~~
可以看到 hello,scala 也是可以运行的。
三、 说明
此时对第二个代码做说明:
//说明
//1. object 表示一个伴生对象,这里可以简单的理解就是一个对象。
//2. HelloScala 就是对象名字,它底层真正对应的类名是 HelloScala$,对象是 HelloScala$类型的一个静态对象MODULE$
为了更清楚查看,这里使用反编译工具 jd-gui.exe,它可以将 class 文件反编译为对应的 java 文件;反编译后只是部分而非完全一样。
//3. 当编写一个 object HellpScala 底层会生成两个.class 文件,分别是 HelloScala 和 HelloScala$。 //是因为在执行的时候做了一个包装
//4. scala 在运行时的流程如下:
//(1)先从 HelloScala 的 main 开始执行
/
/public static void main(String
[
] paramArrayOfString)
//
{
//
HelloScala..MODULE$.main(paramArrayOfString);
/
/}
//(2)然后调用 HelloScala$类的方法 HelloScala$.MODULE$.main
//(3)即执行了下面的代码
/
/public void main(String[] args)
//
{
//
Predef..MODULE$.println(“hello,scala!~~”);
//} //换言之真正起作用的主函数代码被包裹在了这个位置
那么为什么会有这样的操作?
因为 Scala 设计者将静态与非静态分成了两个部分:认为静态不属于面向对象的范畴,拿掉了静态,但是 java 里有静态中心,所以它就把一个类天然的分成两个部分。例如一个 object 分成两部分,非静态的就写在这里面,静态的就写在与它同名的 object 里。如果只写了一个 object,那么就生成了两个文件 HelloScala 和 HelloScala$,就相当于做了一个包装。这里只稍做讲解,因为会涉及到伴生对象和伴生内核关系,点到为止。
以上第一个入口的小程序就写完了。
四、 试验
接下来写一个试验:如果使用 scala 执行 javac 编译器请思考是否可行?
尝试:
在编译器里输入 dir 得到:
D:\scalademo>dir
驱动器 D 中的卷是 新加卷
卷的序列号是500D-45D5
D: scalademo 的目录
2018/11/10 10:25
<DIR>
2018/11/10 10:25
<DIR>
2018/11/10 10:23
423 He HelloJava.class
2018/11/10 10:23
113 He HelloJava.java
2018/11/10 10:25
638 He HelloScala$.class
2018/11/10 10:25
586 He HelloScala.class
2018/11/10 10:41 1,072 He HelloScala.scala
5个文件 2,832字节
2个首录 96,280,621,056可用字节
可以看到有 HelloJava,执行:
D:\scalademo>scala HelloJava
hello,java!
可以看到使用 scala 去装载它编译的字节,发现没有问题。那么反过来用 java 去执行 scala,那么就不一定了,因为范围比较大,且有可能会报错:
D:
\
scalademo>java Helloscala
Exception in thread “main” java.lang.NoClassDefFoundError: scala/Predef$
发现确实报错,但是也再次证明编译器之间的确有相通的地方。因为 java 运载的编译器与 scala 的编译器都是同一个设计者写的,所以做了一些兼容,但是要注意并不是全部。
本节课的案例就讲解到这里。