[Scala]002-变量

变量(variable),在Scala中,有可变、不可变之分:

  • var,可变变量,变量(variable),在程序运行过程中其值可能发生改变,适用于OO;
  • val,不可变变量,value(值),可理解为常量(final),在程序运行过程中其值不会发生变化,适用于FP。

【定义/声明】变量
在这里插入图片描述
注意:
1)变量(不管是var、还是val),定义时必须初始化。否则报错!

scala> var a:Int
<console>:7: error: only classes can have declared but undefined members
(Note that variables need to be initialized to be defined)
       var a:Int
           ^

scala> val a:Int
<console>:7: error: only classes can have declared but undefined members
       val a:Int
           ^

scala> var a:Int = 1
a: Int = 1

scala> var a:String = "1"
a: String = 1

上述报错提示:只有类才能声明,而不定义成员。

2)val变量,一旦初始化,就不可再被赋予新值,即 无法再改变它的值了。

scala> val a = 123 //定义一个val变量
a: Int = 123

scala> a = 456 //val变量一旦初始化,就不可再被赋值,会报错!reassingnment重新分配
<console>:8: error: reassignment to val
       a = 456
         ^

scala> val a = 456 //这表示又定义了一个变量名同为a的局部val变量。而不是重新赋值,因为重新赋值时 变量名前是不带val关键字的
a: Int = 456

3)var变量,在其初始化后,在它的生命周期内,可被多次重新赋值。

scala> var a = 789 //定义var变量
a: Int = 789

scala> a = 100 //这是重新赋值。因为变量名前没有var关键词
a: Int = 100

scala> a
res6: Int = 100

scala> a = 10086 //这还是重新赋值。因为变量名前没有var关键词
a: Int = 10086

scala> a
res8: Int = 10086

4)在定义变量时,数据类型是可选的(不显示指定数据类型),但却在上述结果中显示了具体的数据类型Int。这是因为Scala自身有数据类型推断能力/机制,Scala编译器可自动理解 省略的具体数据类型,即根据值的类型来推断出变量的所属类型。当然,为了代码的可读性,可自行添加变量数据类型的声明。

scala> val str:String = "不可变变量"
str: String = 不可变变量

scala> var num:Double = 10
num: Double = 10.0

5)关于变量名,可遵循以下几个原则:

  • 下划线或其他符号、字母开头(但不要使用$开头,因为以$开头的标识符为保留的Scala编译器产生的标志符使用),后接字母、数字或符号;
  • 作用域较短的变量使用短名字:如isjsks等可用于循环中;
  • 作用域较长的变量使用长名字,像那种无需加以说明便可理解的名字。另外,使用外部APIs应该用长的,如Future.collect,而不是Future.all
  • 避免使用保留字;
  • 不要在不同用途,重用相同的名字;
  • 使用通用的缩写,避开隐秘难懂的缩写。
scala> val empty_? = true //以下这些变量名在Scala中都是合法的
empty_?: Boolean = true

scala> val _s = "abc"
_s: String = abc

scala> val + = "plus"
+: String = plus

scala> val `yield` = 100
yield: Int = 100

scala> val ** = "star"
**: String = star

scala> val name = "lilei"
name: String = lilei

6)变量花式定义

// 赋值为 _,表示缺省值(如0、0.0、nul、false等)
scala> var d:Double = _
d: Double = 0.0

scala> var i:Int = _
i: Int = 0

scala> var s:String = _
s: String = null

scala> val x,y = 0 //两个变量赋同一个初始值
x: Int = 0
y: Int = 0

scala> val x,y:Int = 1
x: Int = 1
y: Int = 1

scala> val x,y = (10, "lily") //给两个变量赋同一个初始值,值是个数组。注意下方赋不同的初始值不一样:同时定义多个变量
x: (Int, String) = (10,lily)
y: (Int, String) = (10,lily)

scala> val (x,y) = (10, "Lily")
x: Int = 10
y: String = Lily

scala> val x,y=10,"Lily" //这是非法的定义
<console>:1: error: ';' expected but ',' found.
       val x,y=10,"hello"
                 ^
scala> val x::y = List(1,2,3,4) //两个英文冒号 表示一个普通元素与一个List的连接操作。即List(1,2,3,4)中的普通元素 1赋值给变量x,List(2,3,4)赋值给变量y
x: Int = 1
y: List[Int] = List(2, 3, 4)

scala> val List(a,b,c) = List(1,2,3)
a: Int = 1
b: Int = 2
c: Int = 3

scala> val List(a, b, _, _, c @ _*) = List(1, 2, 3, 4, 5, 6, 7) //也可以用Array、Seq
a: Int = 1
b: Int = 2
c: Seq[Int] = List(5, 6, 7)

scala> val regex = "(\\d+)/(\\d+)/(\\d+)".r //使用正则表达式定义变量
regex: scala.util.matching.Regex = (\d+)/(\d+)/(\d+)

scala> val regex(year, month, day) = "2019/05/07"
year: String = 2019
month: String = 05
day: String = 07

7)lazyvaldef三者区别

  • val,在定义的同时,就完成求值,并保持不变
scala> val t = System.currentTimeMillis //马上求值
t: Long = 1557236549316

scala> System.currentTimeMillis
res5: Long = 1557236561174

scala> t //保持不变
res6: Long = 1557236549316
  • 定义变量时加上lazy关键字,作用是 实现延迟执行,只有在使用时才会执行初始化
scala> lazy val t = System.currentTimeMillis
t: Long = <lazy>

scala> System.currentTimeMillis //此时还没使用变量 t
res7: Long = 1557236756473

scala> t //正在使用
res8: Long = 1557236761901

scala> import scala.io.Source._
import scala.io.Source._

scala> fromFile("/usr/local/src/lianxi_scala/HelloWorld.scala").mkString //读取某个文件
res29: String =
"object HelloWorld {
        /*这是第一个scala程序
         *改程序将输出Hello world
        */
        def main(args: Array[String]) {
                println("Hello,world!!")
        }
}
"
scala> val info = fromFile("/usr/local/src/lianxi_scala/HelloWorld.scala").mkString //直接输出了!!
info: String =
"object HelloWorld {
        /*这是第一个scala程序
         *改程序将输出Hello world
        */
        def main(args: Array[String]) {
                println("Hello,world!!")
        }
}
"
scala> lazy val info = fromFile("/usr/local/src/lianxi_scala/HelloWorld.scala").mkString //不使用它时,是不会直接读出内容的。只有在第一次使用时,读取、真正访问。
info: String = <lazy>

scala> lazy val info = fromFile("/usr/local/src/lianxi_scala/HelloWorld.scala222").mkString //而如果我不小心写错文件名或其他,这是不会报错的!!
info: String = <lazy>

scala> info // 真正执行时才会报错!而不使用lazy将会立刻报错。
java.io.FileNotFoundException: /usr/local/src/lianxi_scala/HelloWorld.scala222 (No such file or directory)
  at java.io.FileInputStream.open0(Native Method)
  ...

这种延迟执行的操作,在编程中有实际意义(视情况而定,有利有弊),比如:为了缩短模块启动时间,可以将当前不需要的某些工作推迟执行;保证对象中其他字段的初始化优先执行;打开一个数据库连接,一般希望只有在使用其引用时才初始化,因为对于程序来说,执行这个操作,可能代价是昂贵的。

  • def,这是定义一个函数/方法,本质和前面不一样。定义时不求值,不过每次使用时都会重新求一次值。
scala> def t = System.currentTimeMillis //定义函数/方法
t: Long

scala> t //每次求的值都不一样
res11: Long = 1557237041648

scala> t //每次求的值都不一样
res12: Long = 1557237042927

scala> def f = 1+2 //定义函数
f: Int

scala> f //虽然求的值一样,但却是重新计算了一次
res13: Int = 3

scala> f
res14: Int = 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值