一门多范式的编程语言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上运行,产生最终的结果

image-20240710191704602

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
}

posted @ 2024-08-20 22:37  shmil  阅读(17)  评论(0编辑  收藏  举报