【Scala---02】Scala 基础 『 变量和数据类型 | 控制语句 | 简写』

本文详细介绍了Scala编程中的变量与常量的定义,包括变量的数据类型、字符串操作、运算符的使用以及`==`与`equals`的区别。此外,还探讨了控制语句,如分支、循环(for、while)、switch语句的实现方式,以及如何通过模式匹配实现类似switch的功能。文章强调了Scala的强类型特性,并提供了代码示例来说明这些概念。
摘要由CSDN通过智能技术生成

1. 变量和数据类型

1.1 变量和常量

  1. 语法

    1. 定义变量:var 变量名:数据类型 = 值 【相当于Java 没有final关键字修饰】
    2. 定义常量:val 常量名:数据类型 = 值 【相当于Java final关键字修饰】
      • 建议:能用常量,就不要用变量
      • 变量名命名规范:
        在这里插入图片描述
  2. 多变量声明

    // 1. 数值
    val (a,b,c) = (1,2,4)
     println(a) //1
     println(b) //2
     println(c)  //4
    
    // 2. 集合:常用于main方法取args参数,比如 val Array(input, output) = args
    val Array(a, b, c) = Array(1, 2, 3)
    println(a) //1
    println(b) //2
    println(c) //3
    
  3. 注意点

    // 1. 常量值无法修改
    val NAME:String = "张三"
    NAME = "李四”  // 报错
    
    // 2. Scala是强引用,因此不可为变量赋不同数据类型的值
    var age:int = 18
    age = "张三"  // 不可将字符串赋值给整型变量
    
    // 3. 声明 常量、变量时,数据类型可以省略,但是初始值不可省略。这样可以自动推断数据类型
    	// 值为整型:Int
    	// 值为小数:Double
    	// 值为布尔:Boolean
    	// 值为字符:Char
    	// 值为字符串:String
    	// 值为():Unit
    val NAME = "张三"   // 会自动推断变量类型,这里会推断为字符串类型
    
    // 4. 关于对象:
    	// (1) var修饰的对象可以修改指向,而val修饰的对象不可以修改修改指向
    	// (2) 对象的属性是否可以修改,取决于属性是用var还是val修饰
    	val PERSON = Person()
    	PERSON = Person()   // 错误
    

1.2 字符串

  1. 字符串拼接

    1. 通过+号连接

      # 方式一:
      println("hello" + "world")
      
      # 方式 而:
      print("hello".concat("world"))
      
    2. 重复字符串拼接

      println("linhailinhai" * 200)
      
  2. 字符串输出

    1. 通过% + format / printf传值:和c语言一样
      var name = "张三"
      var age = 18
      // print()不换行,println()换行
      printf("name: %s age: %d\n", name, age)  
      printf("name: %s age: %d\n".format(name, age)) 
      

      能够实现前缀填充:%s表示字符串,16表示最终的字符串长度,0表示不足的部分使用0填充,而%是格式说明符的开始。请注意,这两种方法都不会改变原字符串的值,而是返回一个新的字符串。

      val s = "123"
      val result = "%016s".format(s)
      println(result)  // 输出:0000000000000123
      
    2. s打头,然后通过${变量名}获取变量值,和shell脚本一样。
      var name = "张三"
      var age = 18
      printf(s"name: ${name} age: ${age}\n")
      
      如果只显示一个变量,{}可以省略,如果有多个变量在{}进行运算,则不可省略:
      var name = "张三"
      var age = 18
      printf(s"name: $name\n")  // ${name} 可以省略花括号
      printf(s"name: ${name + age}\n")  // 此时,花括号不可省略
      
  3. 三引号字符串:方便写SQL

    // s打头,每个行用 | ,最后.stripMargin 
    val sql = s"""
    	| select *
    	| from table
    	| where name = ${name}
    	| 	and age > ${num}
    """.stripMargin
    // stripMargin 的作用就是忽略前后空格、以及中间的|等符号,也就是说只剩下SQL语句
    
  4. 关于字符串中的转义:

    1. \n在字符串中代表着换行,如果想要字符串中显示\n,着需要转移一下,即\\n适用于双引号和三引号。
    2. 使用双引号和三引号时,即"xx""""xxx""",边界是双引号。如果字符串中要出现",则只能使用三引号+转义"""xx\\"x"""
      // 例子:
      val str = s"""${event_day}的结算侧【补贴分润】数据存在<font color=\\"red\\">**异常**</font>,可能存在的问题:\\n > ①会员ID等字段异常 <= 0; \\n > ②补贴数据的会员id和cpuuser的会员id对不上 \\n\\n 需要评估是否正常。这些用户的【预计补贴】总金额为 ${row.getAs(0)}, 【实际补贴】总金额为 ${row.getAs(1)}。\\n AFS数据地址:${check_result_fail_afs_path_data_side.format(event_day)}""".stripMargin
      

1.3 数据类型

Scala中没有基本数据类型,只有引用数据类型:分为 基本引用数据类型非基本引用数据类型两类

  1. 基本引用数据类型包含 (Byte, Short, Char, Integer❌ Int✅, Long, Float, Double, Boolean) + Unit

    Unit 相当于 Java中的 void,在这里属于基本数据类型,其只有一个值,即()。比如val a = ()此时,a为Unit类型。

  2. 非基本引用数据类型:基本引用数据类型之外的属于非基本引用数据类型,比如String
  3. 重要父类 / 子类:
    1. Any类,是所有类的父类,等价于Java的Object
    2. AnyVal 类是所有基本引用数据类型的父类
    3. AnyRef类是所有非基本引用数据类型的父类。
    4. Nothing是所有引用数据类型的子类。应用场景:一个函数没有明确返回值时指定
  4. 引用类型关系图:

在这里插入图片描述

细节:

  1. 引用数据类型的默认值:
    1. 9种基本引用数据类型:
      1. Byte、Short、Int、Float、Double默认值都是 0
      2. Char默认值是\u0000
        object Test {
           var c:Char = _
           def main(args: Array[String]): Unit = {
              println(this.c)  // 输出:'\u0000'
         }
        }
        
      3. 布尔类型默认值是false
      4. Unit默认值是()
    2. 非基本引用数据类型:null
  2. 只有基本引用数据类型部分可以不写数据类型,自动推断类型。而引用数据类型必须指定数据类型,否则会报错。
    1. 字符串默认是String。比如:val name = "zhangsan"
    2. 整数默认是Int。比如:val age = 15
    3. 整数+L 默认是Long。比如val age = 15L
    4. 小数默认是Double。比如:val money = 150.0
    5. 小数 + F 默认是Fl0at。比如:val money = 150.0F
    6. 字符默认是Char。比如:val c = 'x'
    7. 布尔默认是Boolean。比如:val is_find = false
    8. () 默认是Unit。比如:val a = ()
    9. ByteShort 无法进行自动推断,必须指名数据类型。比如val a:Byte = 1
    10. 引用数据类型必须指定数据类型。比如:val person:Person = null
  3. Nothing vs Unit vs Null
    1. Unit 用于方法无返回值的情况
    2. Nothing 用于非方法的代码块无返回值的情况
    3. Null 是非基本引用对象没有赋值的默认值
      在这里插入图片描述
  4. 集合类型的泛型很容易和Java中的数组弄混:
    • Java中用<>表示泛型,[]用来定义数组:int[] a = {0, 1, 2}; Array<String> = new Array("aaa", "bbb", "ccc")
    • Scala中用[]泛型:Array[Int] a = Array(0, 1, 2) // 使用伴生对象创建数组
    // 访问`Array`:
    val arr = new Array(10, 20, 30)
    println(arr(0)) // 输出第一个元素10
    

1.4 代码块

在Scala中:

  1. 所有代码都是代码块
  2. 最后一行代码的结果就是返回值
    1. 函数无返回值可用Unit
    2. 代码块无返回值可用Nothing
object Test {
	def main(args: Array[String]): Unit = {	
	// 所有的代码都是代码块
	   // 表示运行一段代码  同时将最后一行的结果作为返回值
	   val i: Int = {
	     println("我是代码块")
	     10 + 10
	   }
	
	   // 代码块为1行的时候  大括号可以省略
	   val i1: Int = 10 + 10
	
	   // 如果代码块没有计算结果  返回类型是unit
	   val unit: Unit = {
	     println("hello")
	     println("我是代码块")
	   }
	
	
	   // 当代码块没办法完成计算的时候  返回值类型为nothing
	   // val value: Nothing = {
	   //	 println("hello")
	   //	 throw new RuntimeException
	   // }
	}
}

1.5 强制转换

调用方法进行强制转换:

// Java  :  
// (1) 基本数据类型的强制转换
int num = (int)2.5
// (2) 引用数据类型的强制转换只发生在父子类之间
Animal animal = new Animal();
if(animal instanceof Dog) {
    Dog dog = (Dog) animal;
}

// Scala :  
// (1) AnyVal的使用to方法
//    1)对象.to方法
val num : Int = "123".toInt   // 这个转换会不安全,转换失败时会造成程序中断。
val num:Int = Try("123".toInt).getOrElse(0) // 转换失败时可以设置指定值,程序能继续运行
//    2) to方法(对象, 默认值)
val num : Int = toInt("123", 0)
// (2) 不能使用to方法的,用asInstanceOf强转
val a:Any = Person()
a.asInstanceOf[Person]

1.6 运算符

在这里插入图片描述

  1. 没有++--运算符
  2. 在Scala中,所有的运算符都是方法。
    // 两者等价
    val a = 10 + 5
    val b = 10.+(5)
    
    println(a, b)  // 输出:(15, 15)
    

1.7 == 与 equals

  • Scala中==equals相同,都是比较两个对象的引用是否是同一个对象。

    Java的==用于比较地址是否相等;equals用于比较内容是否相等。

  • 如果要比较地址是否相同,用.eq()方法
    val s1 = "abc"
    val s2 = new String("abc")
    
    println(s1 == s2)
    println(s1.eq(s2))
    
    // 输出结果:
    true
    false
    
  • 如果要比较内容是否相等使用sameElements
    val arr1 = Array(1, 2, 3)
    val arr2 = Array(1, 2, 3)
    
    if (arr1 sameElements arr2) {
      println("The arrays are equal.")
    } else {
      println("The arrays are not equal.")
    }
    

2. 控制语句

2.1 分支语句

在Scala中,有if、if-else、if-else if-else,用法和Java一样。没有三元运算符、switch。

// 1. 没有三元运算符,但是可以用 if语句等价替换。
val a = if(10 > 1) 100 else 50

// 2. 没有swith,但是可以使用模式匹配等价替换,后面详细介绍

2.2 循环语句

(1)for循环

  1. 只有for-each循环,没有递增for循环:

    // 1. 左闭右闭 []
    for(i <- 1 to 10) {
    }
    
    // 2. 左闭右开 [)
    for(i <- 1 until 10) {
    }
    
    // 3. 循环步长
    for(i <- 1 to 10 by 2) { // 步长为2,故结果为:1 3 5 7 9
    }
    
    // 4. 遍历集合
    for(i <- 集合对象){
    }
    

    注意:在方法体内不能修改i的值,会报错。

  2. 循环守卫

    for(i <- 1 to 10 if i != 5) { // 排除5
    }
    
  3. 一个for循环内定义多个变量

    for(i <- 1 to 4; j <- 1 to 5) {
    	println(s"i = $i, j = $j")
    } 
    // 输出:
    i = 1, j = 1
    i = 1, j = 2
    i = 1, j = 3
    i = 1, j = 4
    i = 1, j = 5
    i = 2, j = 1
    i = 2, j = 2
    i = 2, j = 3
    i = 2, j = 4
    i = 2, j = 5
    i = 3, j = 1
    i = 3, j = 2
    i = 3, j = 3
    i = 3, j = 4
    i = 3, j = 5
    i = 4, j = 1
    i = 4, j = 2
    i = 4, j = 3
    i = 4, j = 4
    i = 4, j = 5
    

(2)while/do-while循环

可以,前者是现在判断后执行;后者是先执行后判断。使用语法和Java一样,但是不推荐使用,推荐后面使用函数式编程的递归方法

(3)循环中断

Scala内置控制结构特地去掉了break和continue,是为了更好的适应 函数式编程,推荐使用函数式的风格解决break和continue的功能,而不是一个关键字,而是通过对象来中断。

// 使用Breaks.breakable()方法来实现中断
// 使用Breaks.break()方法代替java中的break关键字
Breaks.breakable(
	for(i <- 1 to 10) {
		if(i == 3)
			Breaks.break() -- 写就是中断,不写就是continue
	}
)

(4)yield关键字结合for循环使用

yield 的作用是把每次迭代生成的值封装到一个集合中,如果把yield去掉那返回给C的值就为Unit。
在这里插入图片描述

2.3 模式匹配

Scala的模式匹配和Java的switch语法很类型。常用来代替分支语句。

  1. Java的switch语法

    // expression可以是表达式,也可以是变量
    switch(expression) {  
        case value1:
            // 代码块1
            break;
        case value2:
            // 代码块2
            break;
        // 可以有任意数量的case语句
        default:
            // 当所有case都不匹配时,执行此代码块
    }
    
  2. switch 用模式匹配 match 代替:

    object TestMatchCase {
    
      def main(args: Array[String]): Unit = {
    
        var a: Int = 10
        var b: Int = 20
        var operator: Char = 'd'
    
        var result = operator match {
          case '+' => a + b
          case '-' => a - b
          case '*' => a * b
          case '/' => a / b
          case _ => "illegal"
        }
    
        println(result)
      }
    }
    

    在这里插入图片描述

    注意:在调用算子时,可以在里面直接写模式匹配。比如:
    在这里插入图片描述

(1) 匹配变量

object Test02_MatchValue { 

  def main(args: Array[String]): Unit = {

    // 匹配类型
    def func2(x:Any):String ={
      x match {
        case i:Int => "整数"
        case c:Char => "字符"
        case s:String => "字符串"
        case _ => "其他"
      }
    }

    println(func2(1515))
    println(func2('\t'))
    println(func2("1515"))
  }
}

(2) 匹配元组

object TestMatchTuple {

  def main(args: Array[String]): Unit = {

    //对一个元组集合进行遍历
    for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {

      val result = tuple match {
        case (0, _) => "0 ..." //是第一个元素是0的元组
        case (y, 0) => "" + y + "0" // 匹配后一个元素是0的对偶元组
        case (a, b) => "" + a + " " + b
        case _ => "something else" //默认

      }
      println(result)
    }
  }
}

(3) 匹配对象及样例类

object Test05_MatchObject {
  def main(args: Array[String]): Unit = {
    val zhangsan = new Person05("zhangsan", 18)

    zhangsan match {
      case Person05("zhangsan",18) => println("找到张三啦")
      case _ => println("你不是zhangsan")
    }
  }
}


class Person05 (val name:String,var age:Int){

}

object Person05{
  // 创建对象的方法
  def apply(name: String, age: Int): Person05 = new Person05(name, age)

  // 解析对象的方法
  def unapply(arg: Person05): Option[(String, Int)] = {
    // 如果解析的参数为null
    if (arg == null ) None else Some((arg.name,arg.age))
  }
}

3. 简写

  1. 代码块只有一行时,可以省略{}
  2. 形参和实参没有参数时,小括号()可以省略。

比如:

object Main {
    def main(args: Array[String]): Unit = {
        def hello():Unit = {
            println("hello")
        }
        hello()
    }
}

可简化为:

object Main {
    def main(args: Array[String]): Unit = {
        def hello:Unit = println("hello")
        hello
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ElegantCodingWH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值