ScalaBase
ScalaBase
Scala是将函数式编程思想和面向对象的编程思想结合的一种编程语言
编写scala注意事项:
1、java中的一些写法,scala中同样适用
2、scala中一行代码就是一个语句,分号可加可不加
3、若想运行一个scala代码,需满足:
要有main方法
将class改为object
4、在scala中的class仅代表一个普通的类,object表示一个类的单例对象
特点
- 多范式
- 面向对象
- 函数式编程
- 兼容Java
- 类库调用
- 互操作
- 语法简洁
- 代码行短
- 类型判断
- 抽象控制
- 静态类型化
- 可检验
- 安全重构
- 支持并发控制
- 强计算能力
- 自定义其他控制结构
变量
/**
* 定义变量的注意事项:
* 1、在scala中创建变量需要使用一个关键字:var
* 2、定义变量的时候,可以不加数据类型,scala会进行自动类型推断
* 3、变量一旦创建了,数据类型就确定了
* 4、可以在创建变量的同时,明确给出数据类型
* 语法: var 变量名:数据类型 = 变量值
* 5、scala中的基本数据类型的写法和java的不太一样
* java scala
* byte Byte
* short Short
* int Int
* long Long
* float Float
* double Double
* boolean Boolean
* char Char
*/
//如何创建一个变量
//1、在scala中创建变量需要使用一个关键字:var
//创建一个int类型的变量
var a1 = 10
println(a1)
//获取该变量的类型
println(a1.getClass)
var a2 = 100
println(a2)
var a3 = "hello"
println(a3)
//创建一个Int类型的变量a2
var a4: Int = 100
println(a4)
常量
/**
* 常量:在程序运行过程中,其值不能发生改变的量
* 定义常量的注意事项:
* 1、定义常量,使用关键字val
*/
//定义一个Int类型的常量
val b1: Int = 100
println(b1)
val b2 = 200
println(b2)
字符串
/**
* 字符串
* 注意事项:
* 1、scala中的字符串数据类型和java中的字符串数据类型是一样的,String类
* 2、可以使用java中String类中的所有方法
*
*
* 数组
* 1、scala中提供了一个类:Array专门表示数组的类型
* 2、scala中的数组,和java中的数组一样,也是有索引的,索引也是从0开始的
* 3、scala中的数组若想通过索引获取元素,得使用小括号
*/
var s1:String = "hello,world,java,spark,flink"
// 调用String类中的方法,将字符串按照指定分隔符进行切分
val arr1: Array[String] = s1.split(",")
println(arr1)
// 获取数组中的第一个元素
println(arr1(0))
println(arr1(1))
println(arr1(2))
println(arr1(3))
println(arr1(4))
/**
* 字符串创建的方式
*/
// 字符串如何表示
// 方式1:使用一对双引号表示
var s2 = "hello"
var s2 = "select" +
"*" +
"from" +
"where"
println(s2)
// 方式2:使用一对三个双引号
// 当字符串很长且需要换行的时候【写sql的时候】
var s3 = """hello"""
var s3 =
"""select
|*
|from
|students
|where
|id='1001'
|""".stripMargin
println(s3)
/**
* 字符串格式化的方式
* 1、和java一样使用 + ,只能是字符串常量之间相加
* 2、使用java中的类,例如StringBuilder
* 3、当存在一个序列【数组或迭代器】的时候,调用方法构建一个字符串
* 4、【在scala中最常用的】 s函数构建字符串
*/
var s1: String = "hello"
var s2: String = "world"
println("hello" + "_" + "world")
val sb: StringBuilder = new StringBuilder()
sb.append("hello").append("_").append("world")
println(sb)
var s1:String = "hello,world,java,flink,spark"
val arr1: Array[String] = s1.split(",")
val s2: String = arr1.mkString("|")
println(s2)
println(s"${s1} _ ${s2}")
运算符
/**
* 运算符,大多数都是函数
* 注意:scala中没有++和--的运算符
*/
var a = 3
var b = 4
println(s"a+b的值为:${a + b}")
println(s"a-b的值为:${a - b}")
println(s"a*b的值为:${a * b}")
println(s"a/b的值为:${a * 1.0 / b}")
println(s"a%b的值为:${a % b}")
//将变量a的值+1
// a = a + 1
// a++
a += 1
println(s"a的值为: ${a}")
println("=" * 50)
流程控制语句
/**
* 控制流程语句
*/
/**
* if语句
*
*/
val sc = new Scanner(System.in)
println("请输入您的年龄:")
val age: Int = sc.nextInt()
if(age>=18){
println("已经成年!")
}else{
println("您还未成年!")
}
/**
* for循环
* scala中的for循环不能写成和java一样的普通for循环或增强for循环
*/
// val arr1: Array[String] = Array("hello", "world", "java", "hello", "spark", "flink")
// for(var i:Int = 0;i<arr1.length;i+=1){
// println(arr1(i))
// }
// for(Int i : arr1){
// println(i)
// }
// scala中的for循环
for (i <- arr1) {
println(i)
}
/**
* while循环
*/
var index = 0
while(index<arr1.length){
println(arr1(index))
index+=1
}
var index = 0
do{
println(arr1(index))
index+=1
}while(index<arr1.length)
// 需求:在控制台输出10行hello world
// 实现1:使用while循环
var i = 10
while(i>0){
println("hello world")
i-=1
}
// 实现2:使用for循环
for(i <- 1 to 10){ // [1,10]
println("hello world")
}
for(i <- 1 until 10){ // [1,10)
println("hello world")
}
I/O流
import scala.io.{BufferedSource, Source}
object Demo2IO {
def main(args: Array[String]): Unit = {
/**
* 输入流
*/
//使用java中的类进行读取数据
// val br: BufferedReader = new BufferedReader(new FileReader("scala/data/words.txt"))
// var line = br.readLine()
// while(line!=null){
// println(line)
// line = br.readLine()
// }
//使用scala中特有的读取文本数据方式
val bs: BufferedSource = Source.fromFile("scala/data/words.txt") //底层是调用了字节输入流的方式读取数据
val lines: Iterator[String] = bs.getLines() // 调用BufferedSource类中的getLines方法,得到一个存储所有行数据的迭代器
//遍历迭代器的第一种方式:调用迭代器中的方法
while (lines.hasNext){ // 判断下一行是否有数据
val line: String = lines.next() // 取出一行数据
println(line)
}
//遍历迭代器的第二种方式:使用scala语法中的for循环
for (line <- lines) {
println(line)
}
/**
* 注意:scala中没有特殊的输出流语法,只能使用java中输出流
*/
}
}
函数
/**
* scala中功能有两种叫法:方法,函数
* 在class中定义的称之为方法
* 在object中定义的称之为函数、
*
* def: 是scala中定义函数或方法的关键字
* main:是函数名或方法名
* args:参数名
* Array[String]:参数类型
* Unit:类似于java中的void,表示该函数或方法没有返回值
* \ = : 后面跟着方法体
*
* def main(args: Array[String]): Unit = {
* }
*/
def main(args: Array[String]): Unit = {
//注意1:若函数定义在当前的object中,可以使用类名直接调用
val res1: Int = Demo4Function.add1(100, 200)
println(res1)
//注意2:若函数定义在当前的object中,可以直接调用,不需要对象名
val res2: Int = add1(11, 22)
println(res2)
//注意3:函数中可以继续定义函数,为我们后面讲解返回值类型是函数做准备
def add2(a1: Int, b1: Int): Int = {
return a1 + b1
}
// //调用必须在定义的后面
val res3: Int = add2(100, 200)
println(res3)
//注意4:函数不能脱离class或object定义
def add4(a1: Int, b1: Int): Int = {
return a1 + b1
}
//注意5: 若调用class类中的方法,必须先创建类的对象
val d1: Demo1 = new Demo1()
val res4: Int = d1.show(100, 200)
println(res4)
Demo2.show2() //可以的, 因为Demo2是被object修饰的,jvm底层会自动创建一个Demo2对象,名字和类名一致,这里相当于对象调用方法
val res5: Int = fun1("1000")
println(res5)
fun2
fun3()
}
//定义格式1: 定义函数,函数特点,只有一个参数和一个返回值
def fun1(s:String):Int={
return s.toInt
}
//定义格式2: 如果函数中,最后一条语句作为返回值的话,return可以省略不写
def fun1(s: String): Int = {
println("开始将字符串s转成Int类型")
//...
s.toInt
}
//定义格式3: 如果函数中,函数体中只有一条语句,大括号也可以不用写
def fun1(s: String): Int = s.toInt
//定义格式4: 如果函数没有参数且没有返回值,小括号也可以不用写,注意,调用的时候,也不能有小括号
def fun2 = println("好好学习,天天向上! fun2")
def fun3() = println("好好学习,天天向上! fun3")
类
/**
* scala是基于java封装的语言,所以也具备面向对象的特点,封装,继承,多态
* 这里基本上都满足java的特点。
*
* 注意事项:
* 1、每一个类必须要有一个主构造方法,在类上面直接定义
* 2、scala中的类的构造方法,也可以发生重载
* 3、除了在类上面定义的主构造方法以外,在类中定义的其他this构造方法都属于辅助构造方法
* 4、辅助构造方法第一句话,必须要调用主构造方法
* 5、scala类中的方法也可以进行方法重写,但是必须要加上一个关键字 override
* 6、定义主构造方法的时候,成员变量默认是不允许直接获取的
* 7、若一个类被object修饰,那么编译过程中会产生两个文件一个带$一个不带,带$的文件中会自动创建一个该类的对象
* 8、若一个类只是被class修饰,那么编译过程中只会一个对象的class文件,如果要调用对象中的方法,需要自己在程序中new出来。
*/
object Demo7Class {
def main(args: Array[String]): Unit = {
// val s1: Student = new Student()
// val s2: Student = new Student()
// val s1: Student = new Student("张三", 18)
// val s2: Student = new Student()
val s1: Student = new Student("张三", 18)
println(s"s1: ${s1}") // 直接打印对象名和java中一样,获取的是当前对象的地址值,默认调用的是父亲中的toString方法
// s1.name // 成员变量默认是不允许直接获取的
// println(s"姓名:${s1.name}")
// s1.name = "李四"
s1._name = "李四" // 若主构造方法上的变量被var修饰的话,就可以修改成员变量值
println(s"s1: ${s1}")
}
}
/**
* 一个标准类中的三大成员:构造方法,成员变量,成员方法
*
* 构造方法:
* 主构造方法:将成员变量定义在类上,一个类本身就作为一个构造方法。
* 辅助构造方法:
*/
class Student { // 类的大括号,就看作主构造方法的方法体。
println("hello world!")
}
/**
* 主构造方法为:Student(name: String, age: Int)
*/
class Student(var _name: String, _age: Int) {
//定义成员变量
def name:String = _name
var age:Int = _age
// 辅助无参构造方法
def this(){
this("默认姓名",18) // 必须要调用主构造方法
}
def setAge(a:Int):Unit={
age = a
}
//重写toString
override def toString: String = s"姓名:${_name}, 年龄:${_age}"
}
class Student(var _name: String, var _age: Int) {
// 辅助无参构造方法
def this() {
this("默认姓名", 18) // 必须要调用主构造方法
}
//重写toString
override def toString: String = s"姓名:${_name}, 年龄:${_age}"
}
scala中的继承 注意事项: 1、子类继承父类的时候,也是使用extends关键字 2、子类可以继承父类中的变量var或常量val 3、子类可以重写父类中被val修饰的常量, 父类中var修饰的变量,子类中可以直接改值 4、多态的调用特点和java中多态一样 5、scala中的类也只能进行单继承scala中也具备抽象类的概念 1、和java一样如果一个方法是抽象方法的话,那么改该方法没有方法体,没有=和{} 2、和java一样如果一个类中有抽象方法的话,这个类一定要定义成抽象类 3、当一个具体的类继承抽象类的时候,必须要实现所有的抽象方法scala中的接口 1、提供了一个关键字用于定义一个接口 trait 2、类要实现接口的话,使用extends 3、一个类可以实现多个接口 4、如果一个类要实现多个接口,多个接口之间使用with连接
函数式编程
/**
* 面向对象编程
* 核心的类型是类,主要的思路将对象在方法中传来传去
* 方法的参数类型可以是一个类【抽象类,接口】,将来调用时可以传入一个对象在方法中,
* 方法的返回值类型也可以是一个类【抽象类,接口】,将来调用完方法时得到一个对象。
*
*
* 面向函数式编程
* 本意就是将函数作为方法或函数的参数类型或返回值
* 1、函数A是函数B的参数,调用函数B的时候,可以将函数A当作参数传入,可以在函数B的内部使用函数A
* 2、函数A是函数B的返回值,调用完函数B的时候,可以得到一个函数A。
*
* 面向对象编程中,区分什么类型的对象,是由类的名字来区分并决定将来要传入什么对象或返回什么对象
* 面向函数式编程中,怎么区分函数【或方法】的种类呢?
* 答:函数是根据参数类型和返回值类型来区分的。
*
* 函数fun1:它的参数类型是一个字符串,返回值类型是一个Int类型
* def show1(s:Student):Unit={
* ...
* }
*
* def show1(f:String=>Int):Unit={
* ...
* }
*
* 函数的数据类型:参数类型=>返回值类型
*
* 一、将函数作为另一个函数的参数类型传入
*/
object Demo13Function {
def main(args: Array[String]): Unit = {
def fun1(s: String): Int = {
s.toInt + 100
}
println(fun1("1000"))
// 函数可以赋值给一个变量
val a1:String=>Int = fun1
println(a1("200"))
// 函数作为参数类型传入
def show1(f:String=>Int):Unit={
println(f("11"))
}
show1(fun1)
//定义函数的时候,参数列表中,不仅有函数的类型,还有具体的值类型
def show1(s: String, f: String => Int): Unit = {
println(f(s))
}
def fun2(s:String):Int={
s.toInt+111
}
def fun3(s:String):Int={
s.toInt+222
}
def fun4(s:String):Int={
s.toInt+333
}
// 调用方式1:自己定义一个符合类型的函数传入
show1("200", fun2)
show1("200", fun3)
show1("200", fun4)
//调用方式2:直接在调用时使用lambda表达式
show1("100", (s: String) => s.toInt + 111)
// show1("100", (s: String) => s.toInt + 222)
// show1("100", (s: String) => s.toInt + 333)
//简化调用方式2写法1,数据类型可以不用写,scala语言会进行自动类型推断
show1("100", s => s.toInt + 111)
//简化调用方式2写法2,如果函数的参数只有一个的话,直接使用下划线代替左边的参数进行使用
show1("100", _.toInt + 111)
}
}
浙公网安备 33010602011771号