Scala 基本数据类型和操作

数据类型

Scala 的数据类型和Java是类似的,所有Java的基本类型在scala包中都有对应的类,将Scala代码编译为Java字节码时,Scala编译器将尽可能使用Java的基本类型,从而提供基本类型的性能优势
8种基本数据类型,位于scala包中:
Byte,Short,Int,Long,Float,Double,Char,Boolean
(Java是Integer ,Character )
Scala中没有基本数据类型的概念,所有的类型都是对象

  • Any :Any是所有其他类的超类
  • AnyRef:Scala里所有引用类(reference class)的基类
  • Unit:只有一个实例值 (),方法返回Unit 相当于返回了Java中的void
  • Null:每个引用类的子类
  • Nothing:在Scala的类层级的最低端;它是任何其他类型的子类型,可以赋值给任何其他类型,用于异常,表明不正常的返回
def error(message: String): Nothing =
  throw new RuntimeException(message)

def divide(x: Int, y: Int): Int =
  if (y != 0) x / y
  else error("can't divide by zero")

相等比较
Java输出结果为false,因为是两个不同的对象

boolean isEqual(Integer x, Integer y) {
   return x == y;
}
System.out.println(isEqual(421, 421));

Scala输出结果为true

scala> def isEqual(x: Any, y: Any) = x == y
isEqual: (x: Any, y: Any)Boolean
scala> isEqual(421, 421)
res1: Boolean = true

scala> def isEqual(x: Int, y: Int) = x == y
isEqual: (x: Int, y: Int)Boolean
scala> isEqual(421, 421)
res2: Boolean = true

Scala中的相等操作==被设计为对类型的表示是透明的,对于值类型,它是自然的(数字或布尔值)相等
对于Java自动包装的数值类型以外的引用类型,==等同于从Object类继承的equals方法的别名,所以Scala不会出现Java字符串比较的陷阱

scala> val x = new String("abc")
x: String = abc
scala> val y = new String("abc")
y: String = abc
scala> x == y
res1: Boolean = true
scala> x eq y
res2: Boolean = false
scala> x ne y
res3: Boolean = true

eqne 方法等同于Java的==比较(引用相等)

创建自己的值类

定义一个值类value class
它必须只有一个参数,它除了defs之外一定没有任何内容,没有其他类可以扩展值类,并且值类不能重新定义equalshashCode

//自定义值类型,而编译的Java字节码将直接使用Int类型
class Dollars(val amount: Int) extends AnyVal {
    override def toString() = "$" + amount
}

scala> val money = new Dollars(1000000)
money: Dollars = $1000000
scala> money.amount
res1: Int = 1000000

此外,还可以定义有方法或字段的微类型,有助于理解

class Anchor(val value: String) extends AnyVal
class Style(val value: String) extends AnyVal
class Text(val value: String) extends AnyVal
class Html(val value: String) extends AnyVal

//有助于避免错误,传错位置
def title(text: Text, anchor: Anchor, style: Style): Html =
  new Html(
      s"<a id='${anchor.value}'>" +
        s"<h1 class='${style.value}'>" +
        text.value +
        "</h1></a>"
)

String 类型

通过双引号包裹起来的字符序列
用三个双引号将字符串包裹起来,原样输出其内容,包括换行符,引号和特殊字符

字符串插值 String Interpolation

从 Scala 2.10.0版本开始,提供了一个新的机制来根据数据生产字符串,通过把变量的引用直接插入到字符串,即字符串插值

val name = "James"
println(s"Hello, $name")  // Hello, James

s"Hello, $name" 是待处理的字符串,通过引号之前的字符来标识

用法

一共有三种字符串插值的方式 s,f,raw ,字符串插值是通过在编译时重写代码来实现的
s 字符串插值器
在任何字符串前加上s,就可以直接在字符串中使用变量了,也可以处理任意的表达式
对嵌入的表达式进行计算,结果调用toString替换表达式
单变量的表达式直接放在$符号后边,否则加上大括号

s"The answer is ${6 * 7}."
println(s"1+1=${1+1}")

f插值器
在任何字符串字面前加上 f,就可以生成简单的格式化字符串,功能类似于其他语言的 printf 函数,使用java.util.Formatter类中的格式,百分号开头

val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall")  // James is 1.90 meters tall

变量定义后如果没有%,默认是%s

raw插值器
与 s 插值器在功能上是相同,但是不执行转义字符,使其保持原样

scala> raw"a\nb"
res1: String = a\nb

操作符

操作符实际是方法

val sum = 1 + 2 // Scala invokes 1.+(2)
val longSum = 1 + 2L // Scala invokes 1.+(2L) 方法重载

 val s = "Hello, world!"
s indexOf 'o' // Scala invokes s.indexOf('o')
s indexOf ('o', 5) // Scala invokes s.indexOf('o', 5)

任何方法也都可以是操作符,除了中缀运算符(有两个操作数,一个左侧,另一个右侧,例如 +),还有前缀和后缀(unary 一元操作符),前缀运算符只有四个+, -, !, ~
在前缀表示法中,方法名称放在调用方法的对象之前(例如,-7中的' - '),实际函数名称是操作符前加上unary_
在后缀表示法中,将方法放在对象之后(例如,7 toLong中的toLong),

-2.0 // Scala invokes (2.0).unary_-

操作符优先级

Scala本身没有运算符,只是把方法作为操作符,Scala使用方法的第一个字符来决定优先级。
例如,如果方法名以开头,则它的优先级高于以+开头的方法。 因此2 + 2 * 7将被计算方式是2 +(2 * 7) 类似地,+++ b *** c(其中a,b和c是变量,+++和**是方法)将被评估为+++(b *** c)

方法第一个字符的优先级,降序排列

* / %
+ -
:
= !
< >
&
^
|
所有字母
所有赋值操作

例外:以等号字符结束的赋值运算符,如果运算符以等号(=)结尾,并且运算符不是比较运算符<=,>=,==或!=之一,则运算符的优先级与简单赋值(=)相同

同一优先级的多个操作符,通过关联性(associativity)决定操作符的分组方式,关联性通过最后一个字符决定,任何以:结尾的方法都是右操作数调用,并传入左操作数作为参数,其他字符结尾的方法在左操作数上调用,传入右操作数

无论关联性如何,操作数从左向右计算

a ::: b ::: c // a ::: (b ::: c) 
a * b * c// (a * b) * c

操作符字符会被Scala编译器通过添加$转化为合法的Java标识符,:->转化为$colon$minus$greater,如果要在Java代码中访问标识符,就必须使用这种内部的表示


对象相等性

==比较,首先确定左侧不是null,然后调用equal方法进行比较,不同于Java中==的含义(对于对象,实际比较的是引用的相等性,Scala中有类似的机制 eq方法)

List(1, 2, 3) == List(1, 2, 3) // true
List(1, 2, 3) == "hello"//  false

富类型

基本数据类型都有对应的 富包装(rich wrapper),可以隐式转换为相应的富类型,它具有额外的方法(例如 min max)

基本类型   富类型
Byte scala.runtime.RichByte
Short scala.runtime.RichShort
Int scala.runtime.RichInt
Long scala.runtime.RichLong
Char scala.runtime.RichChar
Float scala.runtime.RichFloat
Double scala.runtime.RichDouble
Boolean scala.runtime.RichBoolean
String scala.collection.immutable.StringOp

控制结构

最大的特点是if, for, try, match和函数调用都会产生一个返回值
break和continue不再使用

if

var filename = "default.txt"
if (!args.isEmpty)
  filename = args(0)

// 通过直接获取返回值,把变量类型设为 val
val filename =
if (!args.isEmpty) args(0)
 else "default.txt"

while 循环

while循环返回值为Unit,表明有一个返回值,称为 unit value,写作()
while循环通过和var类型一同出现,不推荐使用

var line = ""
while ((line = readLine()) != "") // 错位的写法
println("Read: " + line)

Scala 中赋值语句的返回值是Unit,同String类型比较,永远为true(不同于C,Java等语言)

for循环

枚举集合

数组,集合,Range类型均可

for( x <- Range ){
   statement(x);
}

<-叫做生成器(generator),实际生成scala.collection.immutable.Range.Inclusive集合

Range 可以是i to j或者i until j
i to j生成的集合范围[i,j]
i until j生成的范围是[i,j)

Range 设定步长
设定每次增加的长度

def to(end: Int, step: Int): Inclusive // 1 to (5, 2)
def until(end: Int, step: Int): collection.immutable.Range // 1 until (5, 2)

嵌套循环
通过分号分隔,将会遍历到每一种可能的组合

for( a <- 1 to 3; b <- 1 to 3){
     println( "Value of a: " + a );
     println( "Value of b: " + b );
}

def grep(pattern: String) =
    for {
      file <- filesHere
      if file.getName.endsWith(".scala")
      line <- fileLines(file)
      trimmed = line.trim //中间可以绑定运算结果到新的变量
      if trimmed.matches(pattern)
} println(file + ": " + trimmed)
grep(".*gcd.*")

过滤
只有满足if条件的才能输出,可以添加多个条件,用分号分隔

for( x <- List
      if condition1; 
      if condition2...
   ){
   statement(s);
}

产生新的集合
使用 for-yield 语法for (enumerators) yield e,for循环每次执行的结果会添加到集合中,返回的集合类型取决于enumerators中的集合类型

def foo(n: Int, v: Int) =
   for (i <- 0 until n;
        j <- i until n if i + j == v)
   yield (i, j)

foo(10, 10) foreach {
  case (i, j) =>
    print(s"($i, $j) ")  // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5)
}

try表达式

在Scala中throw 表达式有返回值,类型是Nothing

val half =
    if (n % 2 == 0)
      n / 2
    else
      throw new RuntimeException("n must be even")

import java.io.FileReader
val file = new FileReader("input.txt")
try {
    // Use the file
} finally {
    file.close() // Be sure to close the file
}

try-catch-finally也有返回值,
如果没有引发异常,则返回try子句
如果抛出并捕获异常,则返回相关catch语句
如果抛出异常但未捕获,表达式根本没有结果
在finally子句中计算的值(如果有的话)会被删除

import java.net.URL
import java.net.MalformedURLException
def urlFor(path: String) =
  try {
    new URL(path)
  } catch {
    case e: MalformedURLException =>
      new URL("http://www.scala-lang.org")
}

match表达式

匹配表达式类似其他语言中的switch表达式,从多种选择中进行选择

区别如下:

  • case类型没有限定(Java中只有整形,枚举和字符串常量)
  • 每个选项语句结尾没有break,会隐含一个break
  • match表达式可以返回一个值
val firstArg = if (args.length > 0) args(0) else ""
val friend =
  firstArg match {
      case "salt" => "pepper"
      case "chips" => "salsa"
      case "eggs" => "bacon"
      case _ => "huh?"
}
println(friend)

变量作用域

Scala中可以在内部作用域中定义一个与外部作用域中的变量具有相同名称的变量
内部变量屏蔽了同名的外部变量,因为外部变量在内部范围内变得不可见

val a = 1;
{
val a = 2 
println(a) //2
}
println(a)  //1
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356

推荐阅读更多精彩内容