Scala学习日记 Day0

本文介绍了Scala编程的基础,包括REPL的工作原理,var和val的区别,以及数学方法和操作符重载。通过实例展示了Scala如何在交互式环境中进行快速尝试和验证,同时解释了类型推断和方法调用的方式。
摘要由CSDN通过智能技术生成

工作如何繁忙,生活如何糟心,至少求知的这一刻是我的…

前言

基于Scala 2.12.14。学的《Scala for the Impatient》,记录每天的笔记,有些名词看的英文,翻得未必准确。
适用对象:Java程序员。尽可能在短时间内建立起Java到Scala的转换,做到能看能写。实际上在学习一门语言,应当逐步抛弃掉固有成见,才能发现其中乐趣。人生苦短,别用Java:(逃。

REPL

Read Evaluate Print Loop. 读取用户输入的表达式,并执行,打印结果的循环。严格来说Scala是没有REPL的。Scala的做法是将用户输入的表达式编译为字节码,并交由JVM执行。只是这过程足够快,造成我们似乎是解释执行的错觉。
REPL的优势在于可将一些开发中的想法直接即时地执行出结果,快速确认可行性。因此需要了解下如何使用交互式的命令行。
安装scala后,并配置了环境变量后,即可在终端中唤出交互式命令行:

scala
# Welcome to Scala 2.12.14 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_281).
# Type in expressions for evaluation. Or try :help.
scala> BigInt.probablePrime
   def probablePrime(bitLength: Int,rnd: scala.util.Random): scala.math.BigInt

tips: 在Scala的交互式命令行中是可以使用tab补全的。

var与val

var与val分别是可变量和不可变量。

scala> val unchangeable = "This is a string."
unchangeable : String = This is a string.
scala> var changeable = 1
changeable: Int = 1

scala> unchangeable = "This is a string too."
<console>:12: error: reassignment to val
       unchangeable = "This is a string too."

scala> changeable = 2
changeable: Int = 2

可以从上代码得出结论:

  • val是不可变量,在给变量初始化后,就不可再修改其值。
  • var是可变量,在给变量初始化后,可再修改其值。

那么什么时候应该使用val,什么时候用var?就如关键字的字面意思,可变量用var,不可变量用val。

再细看代码,从Java中,我们申明一个变量必然需要申明它的类型,不论是具体类型还是泛型。而在Scala中,在给变量初始化时即可从其值自动推导类型。

当然,我们也可显式地为变量确定类型:

val foo: String = "String"
val bar: Any = 1

val i, j = 2
var foobar, barfoo: String = null

常用类型

Scala有一些常用类型:Byte, Char, Short, Int, Long, Float, Double, Boolean。看起来似乎是Java中的包装类,事实上,Scala也只是类似Java,并不是复用的Java基本类型的包装类,它提供了比Java更多的便捷方法。

scala> 1.toString()
res1: String = 1
scala> 1.to(3)
res2: scala.collection.immutable.Range.Inclusive = Range 1 to 3

上边的代码在Java中简直是不可想象的事情,一个基本类型怎么可能可以调用方法呢?实际上,Scala没有Java中基本类型的概念,但它的编译器在将Scala代码编译成字节码时,会尽可能使用Java的基本类型。
这些数据类型也没有直接提供这些方法,而是编译器将其隐式转换为xxxOps对象(如StringOps)或Richxxx对象(数值类型),比如一个上述代码,1被转换为RichInt对象,由RichInt类提供便捷的操作方法。
试试12.3.toInt?

数学方法与操作符重载

+, -, *, /, %,一切有同Java。需要注意Scala中没有++和–操作,但提供了+=和-=,因此可以+=1和-=来替代。
那么位操作呢?&, |, ^, ~, <<, >>, >>>,同Java。

一些奇怪的调用方式:

a + b
// 等价于
a.+b

1.to(3)
// 等价于
1 to 3

实际上这是操作符重载特性,上边的+和to实际上都是方法,如果接触过C++或Python,就会对操作符重载有了解,有兴趣自己搜索。通过操作符重载,Scala定义了一些数据类型的数学操作,如BigInt和BigDecimal。

scala> val n: BigDecimal = 123.4
n: BigDecimal = 123.4
// 在Java中,这可是对象,无法使用*和/这样的运算符,得老老实实调用方法
scala> n * 2 / 2
res4: scala.math.BigDecimal = 123.4

更抽象地去看, a method b 等价于 a.method(b)。在Java中,更常用obj.method(param)这种方式调用方法。至于哪种方式更适合工程实践,那就仁者见仁智者见智了。

调用方法

常见调用方法

在上一节实际上已经有两种方法等价调用方式了:

  • a method b
  • a.method(b)

在方法无入参的情况,可以省略(),如

scala> "String".sorted
res5: String = Sginrt

类似Java中的静态方法调用:

// 这里的_等价于Java中的*
// 所有scala开头的package,都可以省略掉scala.,因此其等价于import math._
scala> import scala.math._
import scala.math._

// 其实更像Java中的import static ...
scala> max(1,2)
res6: Int = 2

apply方法调用

特殊的方法: apply。当类实现了名为apply的方法时,会发生一些令Javaer惊讶的事情:

scala> val str = "str"
str: String = str

// 这是方法调用吗?str是函数吗?
// 在上边刚申明的str变量是String类型,不是函数/方法
scala> str(1)
res7: Char = t

当类实现了名为apply的方法时,用括号传递给类实例或单例对象名一个或多个参数时,Scala会在相应的类或对象中查找方法名为apply且参数列表与传入的参数一致的方法,并用传入的参数来调用该apply方法。
当然也可显式地调用apply方法:

scala> str.apply(1)
res8: Char = t

因此Scala中会出现一些明明没有调用new对象,却又能生成对象的调用:

// Java中,应当是new BigInteger(123)
// 但在Scala中,它调用的是apply方法,该apply方法创建了一个BigInt对象。
val bi = BigInt(123)

无参方法调用注意事项

当一个方法本就无参,如果又想对输出结果调用apply方法:

// 期望输出s
scala> "str".sorted(1)
<console>:15: error: type mismatch;
 found   : Int(1)
 required: scala.math.Ordering[?]
       "str".sorted(1)

可以通过以下方法规避:

scala> "str".sorted.apply(1)
res10: Char = s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值