一门多范式的编程语言Scala学习的第一天-简介
Scala
1、Scala简介
1.1Scala的介绍
- scala是一门多范式的编程语言
- Scala是把函数式编程思想和面向对象编程思想结合的一种编程语言
- 大数据计算引擎spark是由Scala编写的
1.2Scala的特性
1.2.1多范式
1.2.1.1面向对象特性
Scala 是一种高度表达性的编程语言,它结合了面向对象编程和函数式编程的最佳特性
- 类和对象:Scala支持类和对象,可以定义属性和方法。
- 继承和多态:支持类的继承和多态,可以创建层次结构和重用代码。
- 抽象类:可以定义抽象类,用于定义接口和实现部分行为
- 封装:支持访问控制修饰符(public,protected,private),实现数据的封装
1.2.1.2函数式编程
- 高阶函数:函数可以作为参数传递给另一个函数,或者从另一个函数返回。
- 不可变性:默认使用不可变数据结构,提高代码的并发安全性。
- 模式匹配:提供强大的模式匹配功能,可以解构复杂数据结构,进行条件判断。
1.2.2兼容JAVA
- 类库调用
- 互操作
1.2.3语法简洁
- 代码行短
- 类型推断
- 抽象控制
1.2.4静态类型化
- 可检验、安全重构
1.2.5支持并发控制
- 强计算能力、自定义其他控制结构
1.3面向函数式编程和面向对象编程的区别
- 在面向对象编程中,我们把对象传来传去,那在函数式编程中,我们要做的是把函数传来传去,而这个,说成术语,我们把他叫做高阶函数。
- 在函数式编程中,函数是基本单位,,他几乎被用作一切,包括最简单的计算,甚至连变量都被计算所取代。在函数式编程中,变量只是一个名称,而不是一个存储单元,这是函数式编程与传统的命令式编程最典型的不同之处。
1.4Scala和Java的编译过程
- 以Scala结尾的文件和以Java结尾的文件都会通过编译之后生成 .class文件,
- 并且由于Scala是基于Java的,因此两者编译之后产生的 .class文件是一样的
- 然后相应的 .class文件会在JVM上运行,产生最终的结果
2、Scala的相关基础用法
注意事项
-
1、如果需要是可运行文件就必须将class改成object
-
2、如果是class仅仅代表的是一个类,如果是object就代表的是一个单例对象
-
3、在Scala中,编写完一句代码结尾不需要加上";"
-
4、Scala文件中可以任意的使用Java的类和方法
Scala的第一个代码,hello world
object demo01HelloWord {
def main(args: Array[String]): Unit = {
println("hello world")
}
}
2.1变量与常量
2.1.1变量
变量: 在程序运行过程中其值可能发生改变的量叫做变量。
object Demo02base {
def main(args: Array[String]): Unit = {
/**
* 定义变量
* 注意:
* 1、变量一旦定义类型就确定了,可以不用手动指定变量的类型,Scala会根据赋予的值自动推断出其类型
* 2、也可以手动的指定变量的数据类型,如:var 变量名:数据类型=值
*
* Scala中的数据类型和Java数据类型的对应关系
* Java: scala:
* byte Byte
* short Short
* int Int
* long Long
* float Float
* double Double
* boolean Boolean
* char Char
*/
var a1=100
println(a1)
//获取a1的数据类型
println(a1.getClass)
//类型不一致无法直接转换a1的值
// a1="hello"
// println(a1)
//类型一致可以直接改变变量的值
a1=200
println(a1)
//定义一个整数类型的完整写法
var a2:Int=100
println(a2)
println(a2.getClass)
// * 其实是一个函数,底层是通过StringBuilder链接字符的
//简化写法将.和()省略
println("="*50)
println("=".*(50))
}
}
2.1.2常量
在程序运行过程中其值不会发生变化的量叫做常量
object Demo03base {
def main(args: Array[String]): Unit = {
/**
* 定义常量:在Scala中定义一个常量,需要使用关键字:val
*/
val a3:Int=50
println(a3)
//常量的值一旦定义就无法改变
// a3=20
}
}
2.2字符串
scala中的字符串String类和Java中的String类是共同的一个字符串类
Java中字符串的功能在Scala中正常使用
object Demo04base {
def main(args: Array[String]): Unit = {
var s3:String="hello,world,java,shujia,scala"
val arr1: Array[String] = s3.split(",")
//直接打印使用逗号切分的数组,打印的是该数组的地址值
println(arr1)
//Scala中的数组和Java的数组一致,具有索引且从0开始
println(arr1(0))
println(arr1(1))
println(arr1(2))
println(arr1(3))
println(arr1(4))
/**
* scala中的字符串拼接方式:
* 1、直接使用+号,这种拼接方式比较消耗性能
* 2、使用String Builder的append方法
* 3、使用Scala特有的函数mkString,该方法的前提是有一组序列
* 4、使用Scala特有的字符串传递方法 s"${变量}" 该方法的底层是使用String Builder方式拼接的
*/
var q1:String="hello"
var q2:String="world"
var q3:String="java"
//方式1
val res1: String = q1 + "|" + q2 + "|" + q3
print(res1)
//方式2
val sb: StringBuilder = new StringBuilder()
sb.append(q1).append("-").append(q2).append("-").append(q3)
println(sb)
//方法3:指定字符串的分隔符
val res2: String = arr1.mkString("|")
println(res2)
//方法4
val res3: String = s"${q1.toUpperCase()}#${q2}#${q3}"
println(res3)
}
}
2.3scala的运算符
import java.util.Scanner
import scala.util.control.Breaks._
object Demo03 {
def main(args: Array[String]): Unit = {
/**
* scala中的运算符
*/
var x:Int=3
var y:Int=4
//这些运算符在Scala中其实都是函数
println(x+y)
println(x-y)
println(x*y)
println(x/y)
println(x%y)
//x乘以1.0之后其数据类型就上升为了double,故结果就会是double类型
println(x*1.0/y)
println("hello"+4)
}
}
2.4条件语句
条件语句分为:
1、选择语句:if
2、循环语句:while,break
- if语句
//条件语句if
val sc: Scanner = new Scanner(System.in)
println("请输入年龄:")
val age: Int = sc.nextInt()
if(age>18){
println("old")
}else{
println("young")
}
- while循环
注意:
1、在Scala语言中,没有++或者--的语法,只有i+=1 或者i-=1
2、在Scala语言中,不存在和Java一样的普通for循环
3、Scala中的for循环写法不一样
//Scala中值存在下面的for循环写法
for(e<-arr1){
println(e)
}
/**
* while循环
*/
var i:Int=0
while (i<arr1.length){
println(arr1(i))
i+=1
}
/**
* 需求:在控制台中输出10行hello world
*/
var j:Int=1
while(j<=10){
println("hello world")
j+=1
}
//使用for循环
for(e<-1 to 10){
println(e)
}
for(e<-1 until 10){
println(e)
}
- 流程控制语句
注意:在scala中没有break或者continue关键字,但是存在breakable
breakable{
for(e<-1 to 10){
if(e==5){
// 底层实现是一个函数,抛出一个异常,终止程序运行
break
}
println(e)
}
}
println("hello")
2.5 Scala中的IO流
注意:对于Scala来说,不存在写文件的方式,有读取文件的方式
-
采用Java中写文件的方式写入,如果文件不存在,则会自动进行创建
-
但是对于读文件,如果文件不存在时会报错
package com.shujia.jichu
import java.io.{BufferedReader, BufferedWriter, FileReader, FileWriter}
import scala.io.{BufferedSource, Source}
object Demo03base3 {
def main(args: Array[String]): Unit = {
/**
* scala中的读取文件的方式
* Source.fromFil 底层是使用了字节输入流读取数据FileInputStream
*/
val bs: BufferedSource = Source.fromFile("scala/data/words.txt")
val iterator: Iterator[String] = bs.getLines()
while (iterator.hasNext){
val str: String = iterator.next()
println(str)
}
//使用for循环的方法
for(e<-bs.getLines()){
println(e)
}
val bw: BufferedWriter = new BufferedWriter(new FileWriter("scala/data/words3.txt"))
bw.write("hello shujia")
bw.newLine()
bw.write("java")
//刷写进入文件
bw.flush()
}
}
2.6异常处理
- Scala中的异常处理和Java中的类似
object Demo04Exception {
def main(args: Array[String]): Unit = {
try{
println(0/0)
//如果上面的错误没有被抛出,使用catch的方式处理,那么下面的语句不会执行
val arr1: Array[Int] = Array(1, 2, 3, 4)
println(arr1(4))
}catch{
//相当于sql语句中的case when
case e:ArithmeticException=>
println("除0异常")
e.printStackTrace()
case e:ArrayIndexOutOfBoundsException=>
println("数组越界")
e.printStackTrace()
case _ =>
println("出现异常")
}finally {
//今后finally中的处理大部分情况下都与释放资源有关
println("finally")
}
}
}
//上面是对异常进行捕获的方式,也可以对异常进行抛出
val sc: Scanner = new Scanner(System.in)
println("输入除数:")
val css: Int = sc.nextInt()
if (css != 0) {
println(10 / css)
} else {
throw new ArithmeticException("除数为0")
}
2.7函数
/**
* def: 定义函数或者方法的关键字
* main: 是函数或者方法的名字,符合标识符的命名规则
* args: 函数形参的名字
* Array[String]: 参数的数据类型是一个元素为字符串的数组
* =: 后面跟着函数体
* Unit: 等同于java中的void 表示无返回值的意思
*
*
* def main(args: Array[String]): Unit = {
*
* }
*
* 在不同的地方定义,称呼不一样
* 函数:在object中定义的叫做函数
* 方法:在class中定义的叫做方法
*/
object Demo05Function {
def main(args: Array[String]): Unit = {
//函数
def add(a1:Int,b1:Int):Int={
return a1+b1
}
val res3: Int = Demo05Function.add1(100, 200)
def fun1(s1:String):Int={
return s1.toInt
}
val res1: Int = add(3, 4)
println(res1)
def add2(a1:Int,b1:Int):Int={
return a1+b1
}
val d1: Demo01 = new Demo01()
val res2: Int = d1.add2(11, 22)
println(res2)
//object中的函数调用方式一:可以直接通过类名进行调用,类似于静态方法一样
val result1: Int = Demo05Function.add1(3, 4)
println(result1)
//调用方法二:可以省略类名,直接调用
val result2: Int = add1(100, 200)
println(result2)
//方法三:如果方法调用的函数只有一个参数的时候,可以将.和小括号用空格代替调用
val result3: Int = Demo05Function fun2 "1000"
println(result3)
add5
}
def add1(a1: Int, b1: Int): Int = {
return a1 + b1
}
def fun2(s1: String): Int = {
return s1.toInt
}
/**
* 函数的定义格式
* 1、函数有返回值,并且最后一句话作为函数的返回值的时候,return关键字可以不写
* 2、函数体只有一句话实现时,大括号可以不写
* 3、如果函数没有参数时,小括号可以省略不写
*/
//方法一
def add3(a1:Int,b1:Int):Int={
a1+b1
}
//方法二
def add4(a1:Int,b1:Int):Int=a1+b1
//方法三
def add5=println("hello")
}
class Demo01{
def add2(a1: Int, b1: Int): Int = {
return a1 + b1
}
}
2.8Scala中的函数递归
递归:方法定义时,调用自身的现象
条件:必须存在函数出口
def main(args: Array[String]): Unit = {
val res1: Int = jiecheng(5)
println(res1)
println(s"5的阶乘是${Demo06Function jiecheng (5)}")
}
//求数的阶乘
def jiecheng(num:Int):Int={
if(num==1){
1
}else{
num*jiecheng(num-1)
}
}
2.9Scala中定义类
定义类的三大要素:构造方法,成员方法,成员变量
构造方法:
-
1、在scala中构造方法的编写和在java中不太一样,类所拥有的大括号中都是构造代码块的内容 2、默认情况下,每一个类都应该提供一个无参的构造方法 3、构造方法可以有许多
object Demo07class {
def main(args: Array[String]): Unit = {
val stu1: student = new student("zhangsan",19)
println(stu1)
val stu2: student = new student("zhangsan", 18, "nv")
println(stu2)
//如果调用的是一个函数的无参构造方法,那么小括号可以不用写
val stu3: Student2 = new Student2
stu3.fun1()
//也可以使用多态的方式创建对象
//多态:父类引用,指向子类对象
val stu4: Object = new student("lisi", 19, "nan")
println(stu4.toString)
}
}
class student(name:String,age:Int){
//相当于构造代码块中的内容
// println("hello world")
/**
* 定义成员变量
*/
val _name:String=name
val _age:Int=age
//下划线表示将来会给其赋予默认值
var _gender:String= _
/**
* 构造方法可以写多个
*/
def this(name:String,age:Int,gender:String){
this(name:String,age:Int)
_gender=gender
}
/**
* 也可以重写其方法
*/
// override def toString:String=super.toString
override def toString: String = {
"姓名:" + _name + ", 年龄:" + _age + ", 性别:" + _gender
}
}
class Student2{
def fun1()=println("shujia666")
}
2.10样例类
- Scala中非常重要的功能:样例类
- 其最重要的特性是:
- 减少创建类时编写的代码两,只需要定义成员变量即可,
- 样例类会自动扩充成员变量,构造方法,并且自动重写了toString等方法
object Demo08caseClass {
def main(args: Array[String]): Unit = {
val t1: Teacher = new Teacher("zhangsan", 20, "shuijiao")
println(t1.toString)
println(t1.name)
println(t1.age)
println(t1.like)
// t1.name="lisi"
t1.like="eat"
println(t1.like)
}
}
/**
* 样例类中的成员变量,编译后默认是被jvm添加了final关键字,用户是改变不了的
* 对于scala来说,默认是被val修饰的
* 如果将来想要被改变,定义的时候需要使用var进行修饰
*/
case class Teacher(name:String,age:Int,var like:String)
2.11 伴生对象
-
在一个Scala文件中
-
如果一个object对象的名字和定义的class类名一样的话,那么称这个object是该class类的伴生对象 直接在main函数中调用object的名字就相当于调用该object中的apply方法 而一般在这个apply方法中会new创建一个上述的类的对象,便于直接调用
-
object Demo09apply {
def main(args: Array[String]): Unit = {
//普通使用的方法
val book: Book = Book.apply("shujia", 666)
println(book)
//使用伴生对象的方式,调用object的名字就相当于调用该object中的apply方法
val book1: Book = Book("shujia", 666)
println(book1)
}
}
object Book{
def apply(name:String,price:Int): Book = {
new Book(name,price)
}
}
class Book(name:String,price:Int){
val _name:String=name
val _price:Int=price
override def toString: String = "书名:" + _name + ", 价格:" + _price
}