Scala学习笔记(三):基础知识
有了可运行的环境,就需要写一些简单的语句来认识一下Scala,本文没有写那么详细,只是为了方便查看、唤起回忆
(1)变量的定义方法
Scala有两种变量
var
val
val 类似于 Java 中的 final 变量,一旦初始化之后,不可以重新赋值
注意:在解释器中,可以用一个之前已经使用了的名字定义新的val
Scala 可以使用两种形式的标志符:字符数字和符号
字符数字:使用字母或是下划线开头,后面可以接字母或是数字
符号:包含一个或多个符号,如+,:,? 等
扩展:
如果你是个 Java 程序员,你会发现 Java 支持的基本数据类型,Scala 都有对应的支持,不过 Scala 的数据类型都是对象(比如整数),这些基本类型都可以通过隐式自动转换的形式支持更多的方法。
譬如:如果调用 (-1).abs() ,Scala 发现基本类型 Int 没有提供 abs()方法,但发现系统提供了从 Int 类型转换为 RichInt 的隐式自动转换,而 RichInt 具有 abs 方法,那么 Scala 就自动将 1 转换为 RichInt 类型,然后调用 RichInt 的 abs 方法。
隐式转换是一项compiler功能,在程序编译(compile)的时候由compiler来进行类型转换代码的产生和替代
一个类型T的隐式作用域就是组成这个类型的所有类的伴生对象(companion object)
(2)函数结构
def max(X:Int,Y:Int):Int={
if(X>Y)
X
else
Y
}
既不带参数也不返回有用结果的函数定义:
def greet()=println("Hello, World !")
如果希望函数返回某个值,但忘了方法定义中的 “=”,Scala 会忽略方法的返回值,而返回 Unit。
在 Scala 中可以省略掉没有参数的方法调用的空括号。
按照惯例,如果调用方法是为了利用方法的“副作用”,此时写上空括号;如果方法没有任何副作用(没有修改其它程序状态),可以省略掉括号。
(3)while循环
var i=0
while (i < args.length) {
println (args(i))
i+=1
}
注意:Scala 不支持++i、i++ 运算,需要使用 i+=1 来自增
扩展:
def approximate(initialGuess: Double) : Double = {
var guess = initialGuess
while(!isGoodEnough(guess))
guess=improve(guess)
guess
}
从简洁度和避免使用 var 变量上看,可以使用函数化编程递归
def approximate(guess: Double) : Double =
if (isGoodEnough(guess)) guess
else approximate(improve(guess))
(4)foreach
使用 while 来实现循环,和使用 Java 实现无太大差异,而 Scala 是面向函数的语言,更好的方法是采用“函数式“风格来编写代码,如下:
args.foreach(arg=>println(arg))
利用 Scala 的缩写形式,如果一个函数只有一个参数并且只包含一个表达式,那么无需明确指明参数,这段代码可以写的更精简些,如下:
args.foreach( println)
(5)for
for(arg<-args)
println(arg)
注意:上述语句中的arg是val类型的
可以在for语句中使用多个过滤器,即添加多个 if 语句
val filesHere = (new java.io.File(".")).listFiles
for( file <-filesHere
if file.isFile
if file.getName.endsWith(".scala")
) println(file)
(6)使用new实例化对象
实例化过程中,可以使用数值或类型作为参数
使用数值实例化
val big=new java.math.BigInteger("123456")
println(big)
使用类型实例化
val greetStrings:Array[String]=new Array[String](3)
greetStrings(0)="Hello"
greetStrings(1)=","
greetStrings(2)="World!\n"
for(i<-0 to 2)
print(greetStrings(i))
注:Array是可变的,Scala访问数组的语法是使用()而非[]。
Array 的 zip 操作符可以用来将两个数组转换成二元组的数组
scala> Array( 1,2,3) zip Array("a","b")
res0: Array[(Int, String)] = Array((1,a), (2,b))
从上述代码可知:zip 分别取两个数组对应的元素组成一个新的二元祖
如果一个数组长度大于另外一个数组,多余的元素被忽略
使用类型作为参数,它的作用类似 Java 的 Generic 类型。
对比如下 Java 代码,可知 Scala 使用方括号来指明类型参数,而非尖括号。
LinkedList number = new LinkedList<Integer>();
(7)上述示例中 for 表达式使用了 0 to 2,其实质是:(0).to(2)。
Scala 中所有基本数据类型都是对象(和 Java 不同),因此 0 可以有方法(实际上调用的是 RichInt 的 to 方法),这种只有一个参数的方法可以使用操作符的写法(不用.和括号)
需要注意的是:该语法只有在明确指定方法调用的接受者时才有效,如:Console println 10
(8)Scala里所有的运算符都是方法调用
1+2
实质上是:(1).+(2)
运算符在 Scala 中并不是什么特殊的语法,任何 Scala 方法都可以作为运算符来使用,是否是运算符取决于你如何使用这个方法
当你使用 s.indexOf(‘o’)时,indexOf 不是一个运算符; 而写成 s indexOf ‘o’时, indexOf 就是一个运算符,因为使用了运算符的语法。
除了类似+的中缀运算符(运算符在两个操作数之间),还有前缀运算符和后缀运算符。
顾名思义,前缀运算符在操作数前面,比如 -7 中的“-”;后缀运算符在操作数的后面,比如 7 toLong 中的 toLong。
前缀和后缀运算符都使用一个操作数,而中缀运算符使用前后两个操作数。
Scala 中实现前缀和后缀运算符的方法都以 unary_-开头;比如: 表达式 -2.0 实际上调用 (2.0).unary_- 方法。
扩展;
Scala 的==和 Java 不同,scala 的==只用于比较两个对象的值是否相同,而对于引用类型的比较使用另外的操作符 eq 和 ne。
scala> val x =new String("abc")
x: String = abc
scala> val y =new String("abc")
y: String = abc
scala> x == y
res0: Boolean = true
scala> x eq y
res1: Boolean = false
scala> x ne y
res2: Boolean = true
(9)用括号给变量传递一个或多个值参数时,Scala会把它转换成对apply方法的调用
这说明了为什么 Scala 使用()来访问数组元素:
在 Scala 中,数组和其它普通类一样,没有什么特别之处,前述示例中的 greetStrings(i) 被转化为 greetStrings.apply(i);
(10)当对带有括号并包括一到若干参数的变量赋值时,将调用变量的update方法,并以括号里的值和等号右边的对象作为参数
如:greetStrings(0)="Hello" 将被转化为 greetStrings.update(0,"Hello")
故前述示例可以写为如下方式:
val greetStrings =new Array[String](3)
greetStrings.update(0,"Hello")
greetStrings.update(1,",")
greetStrings.update(2,"world!\n")
for(i <- 0 to 2)
print(greetStrings.apply(i))
(11)List-不可变的同类对象序列,其索引基于0
Scala 中数组的元素是可以被修改的,如果需要使用不可修改的序列,Scala 提供了 Lists。
List 提供了一个 :: 方法用来向 List 中添加一个元素,:: 方法(操作符)是右操作符,也就是使用 :: 右边的对象来调用它的 :: 方法
val oneTowThree = 1 :: 2 ::3 :: Nil
println(oneTowThree)
Scala 规定所有以 : 开头的操作符都是右操作符,如果你自己定义以 : 开头的方法(操作符)也是右操作符
对某个列表调用方法时,似乎这个列表发生了改变,而实际上只是用新的值重建了列表然后再返回
Nil是空列表的简写
省略方法介绍
扩展:
面向函数的编程语言的一个特点是调用某个方法不应该有任何副作用:参数一定,调用方法后,返回一定的结果,而不去修改程序的其它状态(副作用)。
这样做的一个好处是方法和方法之间关联性较小,从而方法变得更可靠,且重用性高。
这个原则意味着变量需要设成不可修改的,进而避免了多线程的互锁问题。
(12)元组(Tuple)-不可变,可包含不同类型的元素,其索引基于1
Tuple 在方法需要返回多个结果时非常有用,可以使用 ._ 或者 索引 来访问元组的元素
val pair=(99,"Luftballons")
println(pair._1)
println(pair._2)
元组的实际类型取决于它的分量的类型,比如上面 pair 的类型为 Tuple2[Int, String],而 (‘u’, ’r’, ”the”, 1, 4, ”me”) 的类型为 Tuple6[Char, Char, String, Int, Int, String]。
目前 Scala 的元组支持的最大长度为 22,如果有需要,可以自己扩展更长的元组。
(13)特质(trait)
该概念接近于Java的接口(interface),所不同的是 Scala 中的 Trait 可以有方法的实现
(14)集(set)
Scala 提供了两种 Sets 类,分两个包定义 Mutable (可变)和 Immutable (不可变),使用同样名称的 Trait
如果使用可修改的集合类( Set 类型),需要使用全路径来指明 Set,如:scala.collection.mutalbe.Set。
缺省情况下 Set 为 Immutable Set。
不可变:
var tempSet=Set("he","she")
tempSet+="it"
println(tempSet.contains("kk"))
将上例中的 var 改为 val 会出现错误,代码如下,
val tempSet=Set("he","she")
tempSet+="it"
println(tempSet.contains("kk"))
错因:对不可变集使用+=,会对 tempSet 重新赋值,因此应该定义变量为var
可变:
import scala.collection.mutable.Set val tempSet=Set("he","she")
tempSet+="it"
println(tempSet.contains("kk"))
该处使用val却不会出现问题
(15)映射(map)
Scala 提供了 Mutable 和 Immutable 两种 Map 类型
用->和+=方法向Map里添加键值对
val romanNumeral = Map ( 1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
println (romanNumeral(2))
(16)任何对象都能调用->方法,并返回包含键值对的二元组
隐式转换
(17)
Scala 引入包的方式和 Java 类似,也是通过 import 语句。
如果需要引入多个类,Scala 使用 “_” 而非 “*”。
和 Java 相比,Scala 的 import 的使用更加灵活:
- 可以出现在文件中任何地方
- 可以 import 对象(singleton 或者普通对象)和 package 本身
- 支持对引入的对象重命名或者隐藏某些类型
使用=>重命名类型,如:
重新定义包名称
import java.{sql => S}
除 String 类型定义在 java.lang 包中,其它类型都定义在包 scala 中。
Scala的每个源文件都隐含了对包java.lang、包scala,以及单例对象Predef的成员引用,可以使用直接使用 Int,Short,String等,而无需再引入包或是使用全称。
StringBuilder 类定义在 scala 包和 java.lang 包中,后定义的 import 会覆盖前面的,因此如果不明确指明,StringBuilder 为 scala.StringBuilder 而非 java.lang.StringBuilder。
扩展:
Scala支持如下两种方式将代码放入包中:
A、
package shop.navigation
class Navigator
B、
package shop.navigation {
class Navigator
}
第二种方法可以在一个文件中定义多个包。
(18)try-catch
Scala 的异常处理和 Java 类似,一个方法可以通过抛出异常而终止
Scala 捕获异常的方法:
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => //handle missing file
case ex: IOException => //handle other I/O error
}
Scala 的 try-catch 可以返回结果,如下示例:
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")
}
Scala 的 finally 语句不管 try 块是否抛出异常,都会执行,所以可以在 finally 块中添加代码以关闭已经打开的文件。
(19)match
Scala 的 match 表达式支持从多个选择中选取其一,类似 Java 中的 switch 语句。
val firstArg = if (args.length >0 ) args(0) else ""
firstArg match {
case "salt" => println("pepper")
case "chips" => println("salsa")
case "eggs" => println("bacon")
case _ => println("huh?")
}
上述代码和 Java 的 switch 相比有几点不同:
A、任何类型的常量都可以用在 case 语句中
B、case 语句无需使用 break
C、缺省匹配为”_”,其作用类似 java 中的 default
scala 的 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?"
}
(20)
脚本必须以结果表达式结束
(21)Scala编译器
Scala的基本编译器:scalac
快速Scala编译器:fsc 停止fsc后台进程:fsc -shutdown
Scala学习笔记(三):基础知识的更多相关文章
- Scala学习笔记--正则表达式基础知识、如何在scala内使用
正则表达式语法:https://msdn.microsoft.com/zh-cn/library/ae5bf541(VS.80).aspx 基础知识:正则表达式30分钟入门教程 http://www. ...
- C#学习笔记(基础知识回顾)之值类型与引用类型转换(装箱和拆箱)
一:值类型和引用类型的含义参考前一篇文章 C#学习笔记(基础知识回顾)之值类型和引用类型 1.1,C#数据类型分为在栈上分配内存的值类型和在托管堆上分配内存的引用类型.如果int只不过是栈上的一个4字 ...
- C#学习笔记(基础知识回顾)之值传递和引用传递
一:要了解值传递和引用传递,先要知道这两种类型含义,可以参考上一篇 C#学习笔记(基础知识回顾)之值类型和引用类型 二:给方法传递参数分为值传递和引用传递. 2.1在变量通过引用传递给方法时,被调用的 ...
- C#学习笔记(基础知识回顾)之值类型和引用类型
一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...
- Quartz学习笔记:基础知识
Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...
- MyBatis:学习笔记(1)——基础知识
MyBatis:学习笔记(1)--基础知识 引入MyBatis JDBC编程的问题及解决设想 ☐ 数据库连接使用时创建,不使用时就释放,频繁开启和关闭,造成数据库资源浪费,影响数据库性能. ☐ 使用数 ...
- .net学习笔记---xml基础知识
一.XML简介 XML是一种标记语言,用于描述数据,它提供一种标准化的方式来来表示文本数据.XML文档以.xml为后缀.需要彻底注意的是XML是区分大小写的. 先从一个简单的XML例子来了解下xml基 ...
- (C/C++学习笔记) 一. 基础知识
一. 基础知识 ● 程序和C/C++ 程序: 根据Wirth (1976), Algorithms + Data Structures = Programs. Whence C: 1972, Denn ...
- C#学习笔记(基础知识回顾)之枚举
一:枚举的含义 枚举是用户定义的整数类型.在声明一个枚举时,要指定该枚举的示例可以包含的一组可接受的值.还可以给值指定易于记忆的名称.个人理解就是为一组整数值赋予意义. 二:枚举的优势 2.1:枚举可 ...
- 数据库学习笔记 - MySQL基础知识
一.数据库基础知识 1.1 Whats's 数据库 数据库(Database,DB):将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合.如:大型-银行存储的信息,小型-电话簿. 数据 ...
随机推荐
- POJ 1190 生日蛋糕 【DFS + 极限剪枝】
题目传送门:http://poj.org/problem?id=1190 参考剪枝:https://blog.csdn.net/nvfumayx/article/details/6653111 生日蛋 ...
- php 引用变量
什么是引用: 官方给的解释是:用不同的名字访问同一个变量内容. 1.普通的变量 运行之后内存空间变化是这样的: 2.引用变量 运行之后内存变化是这样的: 几乎没有什么变化. 3.使用unset 销毁的 ...
- asp.net 在repeater控件中加按钮
在repeater中加入方法有两种方法: 第一种:是对repeater控件的行添加OnItemCommand事件,添加方法也是有两种 1.在设计页面中,选中repeater控件右击==>属性== ...
- java GZIP 压缩数据
package com.cjonline.foundation.cpe.action; import java.io.ByteArrayInputStream; import java.io.Byte ...
- UGUI防止点击穿透
if (!IsPointerOverGameObject(Input.mousePosition)) { } public static bool IsPointerOverGameObject(Ve ...
- AngularJS 控制器函数
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- bootstrapTable 问题
bootstrapTable引用问题 $("#table").bootstrapTable({ // 对应table标签的id method: 'post', url: 'abc' ...
- NPOI操作excel(通过获取批注信息给excel动态赋值)
private string fileName = null; //文件名 private IWorkbook workbook = null; private FileStream fs = nul ...
- Spring的声明式事务----Annotation注解方式(1)
这里列一个小的demo工程,直接利用Spring的jdbcTemplate访问Mysql数据库. 工程结构: 数据库中的tbl_student表结构如下: 数据实体类Student.java代码如下: ...
- react初学
react和vue一样都是mvvm的这种开发模式. 下载js文件 引入HTML文件里 <!DOCTYPE html> <html> <head> <scrip ...