Scala的全称为Scalable Language,即“可伸缩的语言”,
其设计目标是希望伴随着用户的需求一起成长。
Scala是一门综合了面向对象和函数式编程概念的静态类型的编程语言,
它运行在标准的java平台上,可以与所有的Java类库无缝操作
Spark,Kafka等底层都是Scala编写的
马丁·奥德斯基
追求简洁高效
决定将函数式编程语言的特点融合到JAVA中,由此发明了两种语言pizza和scala
JDK5.0泛型、增强for循环、自动类型转换等都是从Pizza引入的新特性
JDK8.0的类型推断、lambda表达式就是从Scala中引入的特性
Scala基于JVM
参考了Java的思想,可以说是源于Java,Java的进阶版
Scala是面向对象的
每个值都是对象,每个方法都是调用。
Scala是函数式的
Scala是功能完整的函数式编程语言,函数式编程以两大理念为指导:
函数是一等公民
程序中的操作应该将输入值映射成输出值,而不是当场修改数据。即方法不应该有副作用
以JVM为运行环境的融合语言
面向对象和函数式编程
与Java兼容
精简的语法
高级语言特性
静态类型
Spark3.0基于Scala2.12
打开IDEA,依次点击Files=>settings=>plungins选项卡,搜索Scala,安装重启即可
在IDEA中依次点击File=>New=>Project,然后选择创建Scala-IDEA工程
在上一步中,此时看到Scala为空,依次点击Create=>Download,选择所需版本后,
点击ok进行下载,下载完成点击finish进入工程
在工程src目录上右点击New=>Scala Class创建
选择Scala Object,输入名称完成创建
在日常的开发中,由于对应软件,如Spark版本的切换,可能导致需要切换Scala的版本,则
可以在Project Structures中的Global Libraries选项卡中进行切换
Scala编译后生成两个文件
一个.class文件,一个$.class文件
类叫做伴生对象的声明类
对象叫做类的伴生对象
Hello.class 程序执行的入口类或者当前对象的伴生类
Hello$.class 当前伴生对象的所属类
object
单例对象和伴生对象是为了解决删除静态static关键字之后,而且要实现静态功能而设计的
基于对象来调用,实现完全面向对象
按住CTRL键,~~,将Scala源码下载下来
1.在线查看
2.下载解压scala-docs-2.11.8.zip
和Java一样
单行注释//
多行注释/* */
文档注释/**
*
*/
代码规范:
使用Tab键
Shift+tab缩进
格式化:CTRL+alt+L
运算符两边各加一个空格
一行不超过80个字符
实例:/chapter2/Test01.scala
Scala的变量分为两种
var 可以被重新赋值
val 不可以修改
var i:Int=10
scala将类型放在后面,表示它的类型并不重要
程序员要关注的东西是变量的名称,业务处理的逻辑
类型是计算机底层需要考虑的问题,跟代码逻辑没什么关系
Scala的编译器是可以对类型自动推断的
能使用常量的地方尽量不使用变量
* 声明变量时,类型可以省略,编译器可以总动推导
* 类型确定后,就不能修改,说明Scala是强数据类型语言
* 变量声明时,必须要有初始值
* var修饰的可修改,val修饰的不可修改
实例:/chapter2/Test02.scala
Scala中一切数据都是对象,都是Array子类
整型分类:
byte,short,int,long
分别是8位,16位,32位,64位
Unit表示空值,null类型只有一个实例值null
nothing类型啥也没有:有可能抛出异常,返回值就可以指定为nothing
2.7.1 自动类型转换
自动提升原则:当有多种类型的数值混合运算时,系统首先自动将所有的数据转换成精度大的那种数据类型
低精度可以赋值给高精度,但反过来不行
(byte,short)和char之间不会自动相互转换,若要转换,则先转换为int类型
2.7.2 强制类型转换
将数据由高精度转换为低精度,就需要使用到强制类型转换
强转换顾好只针对最近的操作数有效,往往会使用小括号提高优先级
2.7.3 数值类型和String类型
1.数值类型转String
val a:Int=12
val s:String=a+“”
2.String类型转数值
+字符串相加
val re1=10/3
println(re1)
val re2:Double=10/3
println(re2)
val re3:Double=10.0/3
==
&& || !
连接多个条件
Scala里面没有++,--等
可以通过+=,-=等来实现
& | ^ ~ < < >> >>>
运算符的本质是一个对象的方法调用
val n1:Int=12
val n2:Int=13
println(n1.+(n2))
if else 特别的地方:
有返回值,定义为当前分支最后一个语句的值。
val res=if(age>=18) "成年" else "未成年"
年龄18,12,6,35,60
####4.4.1范围数据循环to
for循环的特性被称为for推导式
//scala 范围遍历,to不是关键字,而是方法调用 0.to(9)
for(i <- 0 to 9)println(i)
for(i<- Range(1,10))println(i)
for(i <- 1 until 10)println(i)
for(i<-Array(10,20,30))println(i)
for(i<- -1 to 3 if i!=2)println(i)
//循环步长,by是一个方法,是Range中的一个方法,(1 to 10).by()
for(i<-1 to 10 by 2)println(i)
for(i<-13 to 30 by 3)println(i)
for(i<-13 to 0 by -2)println(i)
for(i<-1 to 10 reverse)println(i)
//步长不能为0
//含笑半步颠
for(i<-1.0 to 10.0 by 0.5)println(i)
//循环嵌套
for(i<-1 to 10;j<-1 to 3)println(i*j)
//循环引入变量
for(i<- 1 to 10){
val j=10-i
println(i,j)
}
for(i<-1 to 10;j=10-i)println(i,j)
//打印输出九层妖塔
for(i<-1 to 9;j=9-i){
println(" "* j + "*"*(2*i-1))
}
val res=for(i<-1 to 10)yield i
1,在Scala中不推荐使用while循环,while必须在外部定义变量,while没有for循环的得到返回值用法
2.真正的函数式语言没有循环的,
Scala内部控制结构去掉了break和continue
// 1. 采用抛出异常的方式退出循环
try{
for(i<-0 until 4){
if(i==3){
throw new RuntimeException
}
println(i)
}
}catch {
case e:Exception=> //什么都不做
}
// 2. 为了简化,使用Scala中的Breaks类的break方法,实现异常的抛出和捕捉
Breaks.breakable(
for(i<-1 to 4){
if(i==3){
Breaks.break();
}
println(i)
}
)
println("=============")
import scala.util.control.Breaks._
breakable(
for(i<-1 to 4){
if(i==3){
break();
}
println(i)
}
)
1.面向对象编程
Scala语言是一个完全面向对象编程语言。万物皆对象
对象的本质:对数据和行为的一个封装
2.函数式编程
函数式编程,解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用
当成一个数学题的求解,所有的都是一个表达式求值的过程
真正的函数式编程语言里没有变量,所有的值来了之后都是常量,所以在scala中能用val的地方就用val
解决问题的过程就是不停的求表达式的值的过程
真正的函数式编程的本质是映射表达式求值。
函数式编程,有一个非常好的特性,对于函数而言是不可变的,这就可以做一个分布式的处理
彼此之间没有额外的影响
def funcname(x:Int,y:Int):Unit={println(x+y)}
关键字 函数名称 参数 返回类型 函数体
函数:为完成某一功能的程序语句的集合,称为函数
方法:类中的函数称之为方法
object Test01 {
def main(args: Array[String]): Unit = {
//定义函数
def sayHi(name:String):Unit={
println("hi "+name)
}
//调用函数
sayHi("gaio")
//调用对象方法
Test01.sayHi("gao")
}
//定义对象的方法
def sayHi(name:String):Unit={
println("hi hi "+name)
}
}
参数
返回值
1.可变参数
2.如果参数列表中存在多个参数,那么可变参数一般放置在最后
3.参数默认值,一般将有参数的默认值
//1.可变参数
def f1(str:String*):Unit={
println(str)
}
f1("alice")
f1("alice","bob")
//2.如果参数列表中存在多个参数,那么可变参数一般放置在最后
def f2(str1:String,str2:String*):Unit={
println(str1,str2)
}
f2("alice")
f2("alice","bob")
//3.参数默认值
def f3(str:String="hi"):Unit={
println(str)
}
f3()
f3("hihihi")
//4.带名参数
def f4(name:String="hi",age:Int):Unit={
println(s"$age $name")
}
f4("bob",23)
f4(age=24,name="hihanpi")
f4(age=23)
能省则省 至简原则细节:
//函数至简原则
def f0(name:String):String={
return name
}
println(f0("hi"))
//1.return 可以省略,Scala会使用函数体的最后一行代码作为返回值
def f1(name:String):String={
name
}
println(f1("hi1"))
//2.如果函数体里面只有一行代码,则可以省略花括号
def f2(name:String):String=name
println(f2("hi2"))
//3.返回值的类型如果能够推断出来,则可以省略(:和返回值类型一起省略)
def f3(name:String)=name
//4.如果函数体里有return,则返回类型不能省略
def f4()={}
//5.如果函数明确声明Unit,则即使函数体中使用return关键字也不起作用
def f5():Unit={
return 1
}
println(f5())
//6.Scala如果期望是无返回值类型,可以省略等号
def f6(){//有时候被称为过程
println("hi")
}
//7.如果函数无参数,那么小括号可以省略,调用时小括号可以省略
def f7(): Unit ={
println("hi")
}
f7()
f7
//8.如果没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f8:Unit={
println("hi")
}
f8
//9.如果我们不关心名称,只关心处理逻辑,那么函数名def可以省略
(name:String)=>{println("hi")} //匿名函数,lambda
在Scala中,函数地位很高,一方面,我们在代码的任何地方,可以声明定义一个函数,非常灵活
函数作为一个表达式的值,可以有更加高阶的用法:
函数可以作为值传递
函数可以作为参数传递
函数可以作为函数返回值返回
val fun=(name:String)=>{println(name)} //匿名函数,lambda
fun("hi")
//定义一个函数,以函数作为参数输入
def f(func:String=>Unit)={
func("hi")
}
f(fun)
f((name:String)=>{println(name)})
//匿名函数的简化原则
f((name:String)=>{println(name)})
//1.参数的类型可以省略,会根据形参进行自动的推导
f((name)=>{println(name)})
//2.类型省略之后,发现只有一个参数,则圆括号可以省略;其它情况:没有参数和参数超过1的永远不能省略圆括号
f(name=>{println(name)})
//3.匿名函数如果只有一行,则大括号也可以省略
f(name=>println(name))
//4.如果参数只出现一次,则参数省略且后面参数可用_代替
f(println(_))
//5.如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
f(println)
匿名函数没有名字(x:Int)=>{函数体}
//实例操作,定义一个“二元运算”函数,只操作1和2两个数,但是具体运算通过参数传入
def dualFunctionOneAndTwo(fun:(Int,Int)=>Int):Int={fun(1,2)}
val add=(a:Int,b:Int)=>a+b
val minus=(a:Int,b:Int)=>a-b
println(dualFunctionOneAndTwo(add))
println(dualFunctionOneAndTwo(minus))
//匿名函数简化
println(dualFunctionOneAndTwo((a:Int,b:Int)=>a+b))
println(dualFunctionOneAndTwo((a,b)=>a+b))
println(dualFunctionOneAndTwo(_+_))
println(dualFunctionOneAndTwo(_-_))
println(dualFunctionOneAndTwo(-_+_)) //b-a
Scala的面向对象和Java的面向对象思想和概念是一直的,类的概念,对象的概念
Scala又补充了很多的功能
package 包名
Scala包的作用-和Java一样
区分相同名字的类
当类很多时,可以很好的管理
控制访问范围
命名规则:只能包含数字,字母,小花仙,小圆点(分隔符),不能使用关键字,不能数字开头
命名规范: com.公司名.项目名.业务模块名.xxx
1.包名和源文件所在路径不要求必须一致
2.花括号嵌套
在Scala中可以为每个包定义一个同名的包对象,
定义在包对象中的成员,作为其对应包下所有class和object的共享变量,可以被直接访问
package object name{}
和Java一样,顶部导入
局部导入,什么时候用,什么时候import
通配符导入_
给包中的类重新起名import java.util.{ArrayList=>JL}
导入相同包的多个函数import java.util.{HashSet,ArrayList}
屏蔽类import.java.util.{ArrayList=>_,_}
注意:
Scala中三个默认导入:
类:可以堪称一个模板
对象:表示具体的事物
1.基本语法
[修饰符]类名
Scala中默认访问权限为public,但是Scala中没有public关键字
private为私有权限,只在类的内部和伴生对象中可用
protected为受保护权限,Scala中受保护权限比Java中更严格,同类、子类可以访问,同包无法访问
private[包名]增加包访问权限,包名下其它类也可以使用
和Java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法
Scala类的构造器包括:主构造器和辅助构造器
基本语法
class 类名(形参列表){ //主构造器
//类体
def this(形参列表){//辅助构造器}
def this(形参列表){//辅助构造器可以有多个}
}
说明:
1.辅助构造器,函数的名称this,可以有多个,编译器通过参数的个数及类型来区分
2.辅助构造方法不能直接构建对象,必须直接或间接调用主构造方法
3.构造器调用其它的构造器,要求被调用构造器必须
实例:/chapter6/Test04.scala
说明:
1.未使用任何修饰符,局部变量
2.使用var 作为类的成员属性使用,可以修改
3.使用val 作为类只读属性使用,不能修改
基本语法:class 子类名 extends 父类名{ 类体 }
Scala是单继承
继承的调用顺序:先调用父类构造器>然后子类构造器
/**
* 调用顺序
* 1.父类的主构造器被调用
* 2.子类的主构造器被调用
* 3.子类的辅助构造器被调用
*/
子类中如果要覆盖父类中的属性和方法,必须要加override关键字
在scala中,属性和方法都是动态绑定的
1.基本语法
定义抽象类
abstract class Person{}//通过关键字abstract标记抽象类
定义抽象属性
var|val name:String//一个属性没有初始化,就是抽象属性
定义抽象方法
def hello():String //只声明而没有实现的方法,就是抽象方法
说明:
只要存在抽象属性和抽象方法,那么这个类必须定义为抽象类
定义了一个抽象类,可以不定义任何的抽象属性和方法
需要子类具体化之后创建 对象才可用
2.继承&重写
如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需要声明为抽象类
重写非抽象方法血药用override修饰,抽血抽象方法则可以不加override
子类调用父类的方法使用super关键字
子类对抽象属性进行实现,父类抽象属性可以用var修饰
子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var
因为var修饰的为可变变量,子类继承之后就可以直接使用,没必要重写
说明:
和Java一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类
scala语言是完全面向对象的语言,所以并没有静态的操作,也没有静态的概念。
但是为了能够和Java语言交互,就产生了一种特殊的对象来模拟类对象,称为单例对象。
若单例对象名与类名一致,则称该单例对象这个类的伴生对象
这个类的所有静态内容都可以放置在它的伴生对象中声明
对于object定义的对象,全局只有一份,在底层,编译后生成两个字节码文件
object Person{
val contry:String="china"
}
说明
单例对象采用object关键字声明