环境安装
Scala运行在 JVM 上,所以需要先安装配置 JDK 环境。
下载 Scala:
- Windows版:scala-2.12.16.zip
- Linux版:scala-2.12.16.tgz
因为学习Scala是为了Spark使用,所以下载的 jdk、Scala 版本最好和Spark官网上要求的一致:
Spark runs on Java 8/11/17, Scala 2.12/2.13, Python 3.7+ and R 3.5+. Java 8 prior to version 8u201 support is deprecated as of Spark 3.2.0. For the Scala API, Spark 3.3.0 uses Scala 2.12. You will need to use a compatible Scala version (2.12.x).
将下载好的Scala进行解压:
tar -zxvf scala-2.12.16.tgz -C /opt/module
配置环境变量:
export SCALA_HOME=/opt/module/scala-2.12.16
export PATH=$PATH:$SCALA_HOME/bin
验证:
scala -version
和 Java 一样,Scala也可以使用 Idea 进行编写。所以还需要安装 Idea 来编写代码。
HelloWorld
使用scalac编译运行
和 Java 的 javac 编译几乎一样。
编写HelloScala.scala
:
object HelloScala {
// Unit 表示返回值为空
def main(args: Array[String]): Unit = {
println("hello world") // scala不需要写分号
}
}
使用scalac
编译成class:
scalac HelloScala.scala
编译后会生成两个文件:
HelloScala.class
HelloScala$.class
运行编译后的class:
scala HelloScala
将class反编译为Java
HelloScala.class
反编译结果为:
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes = "\006\001%:Q\001B\003\t\002!1QAC\003\t\002-AQAE\001\005\002MAQ\001F\001\005\002U\t!\002S3mY>\0346-\0317b\025\0051\021a\002\037f[B$\030PP\002\001!\tI\021!D\001\006\005)AU\r\0347p'\016\fG.Y\n\003\0031\001\"!\004\t\016\0039Q\021aD\001\006g\016\fG.Y\005\003#9\021a!\0218z%\0264\027A\002\037j]&$h\bF\001\t\003\021i\027-\0338\025\005YI\002CA\007\030\023\tAbB\001\003V]&$\b\"\002\016\004\001\004Y\022\001B1sON\0042!\004\017\037\023\tibBA\003BeJ\f\027\020\005\002 M9\021\001\005\n\t\003C9i\021A\t\006\003G\035\ta\001\020:p_Rt\024BA\023\017\003\031\001&/\0323fM&\021q\005\013\002\007'R\024\030N\\4\013\005\025r\001")
public final class HelloScala {
public static void main(String[] paramArrayOfString) {
HelloScala$.MODULE$.main(paramArrayOfString);
}
}
HelloScala$.class
反编译结果为:
import scala.Predef$;
public final class HelloScala$ {
public static HelloScala$ MODULE$;
public void main(String[] args) {
Predef$.MODULE$.println("hello world");
}
private HelloScala$() {
MODULE$ = this;
}
}
经过反编译成java后,可以大致了解其运行机制:
- 我们运行的
HelloScala
的main()
方法,其实实际调用的是HelloScala$
的MODULE$
对象的main()
方法 HelloScala$
的MODULE$
对象实际上就是我们在Scala中创建的object HelloScala
,叫做伴生对象
(把HelloScala
叫做伴生对象的伴生类,把HelloScala$
叫做伴生对象的所属类)HelloScala$
的main()
方法不是static
的,需要通过对象才能调用HelloScala$
的MODULE$
对象就是本身,所以拥有打印hello world
的main()
方法
经过上面的分析,我们可以发现,我们只需要用java
去执行HelloScala
类的静态main()
方法也可以执行Scala编译的结果,但是需要引入scala.Predef$
(在Scala的lib包中有):
# 注意:Linux的jar包中间以冒号分隔,Windows的以分号分隔
java -cp $SCALA_HOME/lib/scala-library.jar: HelloScala
使用Idea编写HelloWorld
在 Idea 中安装插件 Scala
,然后便可以像编写Java项目一样正常编写Scala了。
开发步骤:
- 使用Idea创建Maven项目,选择 JDK 1.8。
- 在
src/main
下创建scala
文件夹,然后Make Directory as
设置成Sources Root
。maven项目中的
java
文件夹可以继续保留着,因为Scala支持Java的大部分类库,所以项目中的Scala、java源文件是可以混合着使用的
- 在项目上右键,选择
Add Framework Support...
,勾选Scala
并配置Scala软件位置,为项目添加Scala框架支持 - 然后可以像Java一样创建一个包
chapter01
- 然后在包内创建
Scala Class
- 选择
Scala Class
后会提示创建Scala的类型:Class
、Case Class
、Object
、Case Object
、Trait
。
此处因为我们需要直接运行HelloWorld,所以可以直接创建Object
伴生对象
package chapter01 // 包名
// object关键字声明一个单例对象(伴生对象)
object HelloWorld {
// 定义 main 方法
def main(args: Array[String]): Unit = {
println("hello world")
System.out.println("lalala") // 在Scala中可以直接使用Java的System类
}
}
伴生对象
为了达到纯粹的面向对象,消除掉Java类中的static
静态属性,Scala使用了伴生对象。
伴生对象用法示例
示例:
Java中的代码Student.java
:
public class Student {
private String name;
private Integer age;
private static String school = "庞各庄小学"; // 此处有static类的静态属性
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public void printInfo() {
// Student.school通过类直接调用了属性,不是纯粹的面向对象
System.out.println(this.name + " " + this.age + " " + Student.school);
}
public static void main(String[] args) {
Student zhangSan = new Student("张三", 18);
Student liSi = new Student("李四", 20);
zhangSan.printInfo();
liSi.printInfo();
}
}
Scala中的转换:Student.scala
package chapter01
// 定义一个类
// 类后面可以直接在括号内声明类中的属性,Scala会自动认为其为构造方法
class Student(name: String, age: Int) {
def printInfo(): Unit = {
// Student类可以直接使用伴生对象Stduent的相关属性和方法,Student.school、
// 表面看起来似乎在School中有一个静态属性school,但是实际上是伴生对象object Student的属性。达到完全的面向对象
println(this.name + " " + this.age + " " + Student.school)
}
}
// 类Student的伴生对象,和类名完全一致,而且必须放在同一个文件中
object Student {
var school: String = "庞各庄小学"
def main(args: Array[String]): Unit = {
val zhangSan = new Student("张三", 18)
val liSi = new Student("李四", 20)
zhangSan.printInfo()
liSi.printInfo()
}
}
编译的class
Scala的Student.scala
最终生成的class。
Student.class
:即class Student
声明的属性、构造方法、方法
import chapter01.Student;
import chapter01.Student$;
import scala.Predef$;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes = "\006\001\0213A\001D\007\001!!Aq\003\001B\001B\003%\001\004\003\005$\001\t\005\t\025!\003%\021\0259\003\001\"\001)\021\025i\003\001\"\001/\017\025\021T\002#\0014\r\025aQ\002#\0015\021\0259c\001\"\0016\021\0351d\0011A\005\002]Bq\001\017\004A\002\023\005\021\b\003\004=\r\001\006K\001\007\005\006{\031!\tA\020\002\b'R,H-\0328u\025\005q\021!C2iCB$XM\035\0312\007\001\031\"\001A\t\021\005I)R\"A\n\013\003Q\tQa]2bY\006L!AF\n\003\r\005s\027PU3g\003\021q\027-\\3\021\005e\001cB\001\016\037!\tY2#D\001\035\025\tir\"\001\004=e>|GOP\005\003?M\ta\001\025:fI\0264\027BA\021#\005\031\031FO]5oO*\021qdE\001\004C\036,\007C\001\n&\023\t13CA\002J]R\fa\001P5oSRtDcA\025,YA\021!\006A\007\002\033!)qc\001a\0011!)1e\001a\001I\005I\001O]5oi&sgm\034\013\002_A\021!\003M\005\003cM\021A!\0268ji\00691\013^;eK:$\bC\001\026\007'\t1\021\003F\0014\003\031\0318\r[8pYV\t\001$\001\006tG\"|w\016\\0%KF$\"a\f\036\t\017mJ\021\021!a\0011\005\031\001\020J\031\002\017M\034\007n\\8mA\005!Q.Y5o)\tys\bC\003A\027\001\007\021)\001\003be\036\034\bc\001\nC1%\0211i\005\002\006\003J\024\030-\037")
public class Student {
private final String name;
private final int age;
public Student(String name, int age) {}
public void printInfo() {
Predef$.MODULE$.println((new StringBuilder(2)).append(this.name).append(" ").append(this.age).append(" ").append(Student$.MODULE$.school()).toString());
}
public static String school() {
return Student$.MODULE$.school();
}
public static void school_$eq(String paramString) {
Student$.MODULE$.school_$eq(paramString);
}
public static void main(String[] paramArrayOfString) {
Student$.MODULE$.main(paramArrayOfString);
}
}
Student$.class
:即 object Student
声明的属性、方法
import chapter01.Student;
import chapter01.Student$;
public final class Student$ {
public static Student$ MODULE$;
private String school;
public String school() {
return this.school;
}
public void school_$eq(String x$1) {
this.school = x$1;
}
public void main(String[] args) {
Student zhangSan = new Student(", 18);
Student liSi = new Student(", 20);
zhangSan.printInfo();
liSi.printInfo();
}
private Student$() {
MODULE$ = this;
this.school = ";
}
}