下载对应的scala版本:https://www.scala-lang.org/download/2.11.12.html
Windows版本安装:
- 点击 scala-2.11.12.msi双击msi文件安装
- 配置Scala的环境变量SCALA_HOME变量,同时在PATH变量中追加xxx;%SCALA_HOME%\bin
- 打开控制台输入scala
C:\Users\Administrator>java -version
java version "1.8.0_161"Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM)64-Bit Server VM (build 25.161-b12, mixed mode)
C:\Users\Administrator>scala
Welcome to Scala 2.11.12(Java HotSpot(TM)64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try:help.
CentOS安装:- 下载 scala-2.11.12.rpm
- 安装配置Scala
[root@CentOSA~]# rpm -ivh scala-2.11.12.rpm
Preparing... ########################################### [100%]1:scala ########################################### [100%][root@CentOSA~]# scala
Welcome to Scala 2.11.12(Java HotSpot(TM)64-Bit Server VM, Java 1.8.0_191).
Type in expressions for evaluation. Or try:help.
scala>
Scala 可以做变量类型自动推断。编译器在编译的时候推断出最终类型。根据字面量的值自动识别类型。
因此Scala中声明一个变量主需要告知编译器该变量的值是常量还是变量。
程序一旦编译后,类型固定,不可以更改。
声明一个变量使用 var
声明的是一个常量使用 val
语法:var|val 变量名[:类型]= 变量值[:类型] 类型可省略
var i=1 (默认Int类型)
由于编译器是可以自动推断出AnyVal类型的变量,因此用户在声明AnyVal类型的变量的时候,无需指定变量类型。
3.3 数值转换
用户可以使用asInstanceOf[类型]这种方式在数值间转换。该方式只适合类型兼容的时候使用。
scala> var i=1
i: Int =1
scala> var b:Byte=i.asInstanceOf[Byte]
b: Byte =1
scala> var b:Byte=i.toByte
b: Byte =1
如果类型不兼容可以使用toInt、toChar 方法等可以将常规参数自动转换为数值类型
scala> var sex="true"
sex: String =true
scala> sex.toBoolean
res2: Boolean =true
scala> sex.asInstanceOf[Boolean]
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
at scala.runtime.BoxesRunTime.unboxToBoolean(BoxesRunTime.java:85)...32 elided
3.4 数组
Scala提供了简便的声明和使用方式,例如声明一个Int类型的数组,
scala> val array:Array[Int]=Array(1,2,3)
scala>array(0)
res10: Int =1
可以通过length和size方法获取数组长度。
3.5 元组
元组是在Scala编程语言中的一种特殊变量。该变量可以组合任意几种类型的变量。构建一个只读的变量类型。
元组中的元素只读,其本身可以修改。
访问元组的成员可以使用_元素下标访问。
scala> var t:(String,Int)=("zs",18)
t:(String, Int)=(zs,18)
scala> t._1
res10: String = zs
scala> t._2
res11: Int =18
注意:一个元组最大允许有22个元素。
四、分支循环
4.1 条件分支-if
使用if可以作为条件分支控制语句,这一点类似与Java
var i:Int=100if(i<10){
println("i小于10:"+i)}elseif(i<20){
println("i小于20:"+i)}else{
print(s"i大于:$i")//小s上下文取值,隐式转化。}if修饰的代码分支可以赋值给一个变量,这里的代码块中不允许使用return。
var i:Int=newRandom().nextInt(30)
var result=if(i<10){
"小"}elseif(i<20){
true}else{
("zhangsan",1)//元组}
4.2 while/do-while
var i=5while(i !=0){
i -=1println(i)}
var i=5do{
i -=1println(i)}while(i!=0)
数组遍历:
var array=Array(1,2,3,4)for(item <- array){
print(item+"\t")}
var array=Array("a","b","c")for( index <-0 to array.length-1){
print(array(index))}
var array=Array("a","b","c")for( index <-0 until array.length){
print(array(index)+"\t")}for循环可以使用多个循环因子:
for(i<-1 to 9;j <-1 to i){
print(s"$i*$j="+(i*j)+"\t")if(i==j)println()}for循环可以嵌套if判断:
for(i<-1 to 9;if(i%2==0|| i%3==0)){
print(s"$i\t")}
数组计算:
var array=0 to 9
val results =for(i <- array;if(i%2==0)) yield i*i
for(i <- results){
println(i)}
模式匹配:
模式匹配是检查某个值(value)是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。
它是Java中的switch语句的升级版,同样可以用于替代一系列的 if/else 语句。
数值匹配:
val x: Int = Random.nextInt(10)
var result= x match {
case0=>"zero"case1=>"one"case2=>"two"case3=>"three"case4=>"four"case _ =>"other"}println(result)
类型匹配:
var array=Array("zs",true,newDate(),1000.0)
var x=array(newRandom().nextInt(array.length))println("x:"+x)
var result= x match {
case v:String =>"name"case v:Boolean =>"sex"case x:Date =>"birth"case x:Double =>"salary"case _ =>"未知"}println(result)
caseclass就像常规类,caseclass适用于对不可变数据进行建模。
与普通的class不同的是,CaseClass创建的对象 == 比较的是对象的内容。
通常用于只读数据的建模。可以简单的使用copy来实现两个对象间的值得传递
当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了apply, unapply,setter, getter 和toString,equals,copy和hashCode等方法
caseclassUser(name:String,age:Int)
var u1=User("zs",19)
var u2=User("zs",19)println(u1==u2)//true
var u1=newUser("zs",19)
var u2=newUser("zs",19)println(u1==u2)//true
var u1=User("zs",19)
var u2= u1.copy(u1.name,20)println(u2)
注意:可见性使用
class 或 trait 关键字之前,
val 或 var 关键字之前 ,
def 关键字之前。如果不指定默认都是public。
7.1 public
Scala 中的默认可见性为 public,默认可见性为 public.
这是逻辑上的,实际上 Scala 中并没有 public 这个关键字,如果你用 public 来声明一个类或成员,编译器会报错
publicclassUser{
//编译器不通过
var id=1
var name="zhanngsan"
var age=18
var birthDay =newDate()}
7.2 Private
1.修饰类:
只能被同包下的子类继承(同包可见),并且同包继承的类也必须是private修饰。
不同包类不可见。因为这样才不会改变原始父类的可见性。
被private修饰的类只能在同包下可用
package com.sxxd.demo08
import java.util.Date
privateclassUser{
//父类
var id=1
var name="zhanngsan"
var age=18
var birthDay =newDate()}package com.sxxd.demo08
privateclassSmallUserextendsUser{
//子类继承,同包可见}2.修饰属性|方法:
表示该属性/方法只能被本类|伴生对象可见,其他均不可见
package com.sxxd.demo08
import java.util.Date
privateclassUser{
private var id=1
var name="zhanngsan"
var age=18
var birthDay =newDate()private def eat():Unit={
println("吃!")}}
object User{
def main(args: Array[String]): Unit ={
val user =newUser()
user.eat()
user.id=2}}
7.3 Protected
1、修饰类:类可以被同包下的其他类访问。或者是同包子类使用。
package com.sxxd.demo09
protectedclassUser{
}package com.sxxd.demo09
classSmallUserextendsUser{
}2、修饰属性和方法
只能在本类或者本类的子类以及半生对象中访问
package com.sxxd.demo09
protectedclassUser{
protected var name:String= _
protected def eat():Unit={
println("eat")}}package com.sxxd.demo09
classSmallUserextendsUser{
}
object SmallUser{
def main(args: Array[String]): Unit ={
val sm =newSmallUser()
sm.eat()}}
7.4 this限定
可以去除伴生对象的可见性:
classStudent(name:String){
var id=1protected|private[this] var sex=true
def sayHello():Unit={
println(this.name)}}
object Student{
def apply(name: String): Student =newStudent(name)}
7.5 package限定
表示当前的类、属性、方法可以在指定的包下可见
classStudent(name:String){
var id=1private[demo01] var sex=true//01包可见
def sayHello():Unit={
println(this.name)}}
object Student{
def apply(name: String): Student =newStudent(name)}
使用implicitly[类型],必须保证当前上下文有且仅有一个隐式值类型,一般这种隐式值变量的声明写在object单例类或者伴生对象中。
object MyImplicits {
implicit val i:Int=2//用作隐式值注入
implicit val s:String="Hello"//用作隐式值注入}
主函数中使用:
object testImplicits {
def main(args: Array[String]): Unit ={
import com.sxxd.demo12.MyImplicits._
val b=implicitly[Int]//当前类文件中,只能有一个隐式值类型
val ss=implicitly[String]//当前类文件中,只能有一个隐式值类型println("b:"+b+"\tss:"+ss)}}
3.2 隐式注入值
要求隐式注入的值一般都会写成柯理化形式并且保证需要隐式注入的值写在最后。
object Myimplicit {
implicit val s: String ="Hello"//用作隐式值注入}
object testImplicit2 {
def main(args: Array[String]): Unit ={
import com.sxxd.demo15_Exception.Myimplicit._
sayholle("zhangsan")sayholle("zhangsan")("不好")sayholle2("buhao","lisi")sayholle2(implicitly[String],"zhansgan")}//柯里化写法
def sayholle(name:String)(implicit msg:String): Unit ={
println(name +"&"+msg)}//当implicit放置在参数上时候,只能放在第一参数上。
def sayholle2(implicit msg:String,name:String): Unit ={
println(name +"&"+msg)}}
consol:
zhangsan&Hello
zhangsan&不好
lisi&buhao
zhansgan&Hello
表示上下文中必须存在这种隐式值A[T]隐式值,否则程序编译出错.
这样可以在上下文中还没有隐式值得时候确保方法能编译成功。
classUser[T]{
def sayHello(t:T): Unit ={
println(t)}}
object MyPrrdefs {
implicit val u1 =newUser[Int]()}
object TestFanxing {
def main(args: Array[String]): Unit ={
import com.baizhi.demo17.MyPrrdefs._
sayInfomation(21)}
def sayInfomation[T:User](msg:T)(implicit u:User[T]):Unit={
u.sayHello(msg)}}
12.5 +A协变
classCovariant[+T](t:T){
}//小给大
val c1 =newCovariant[Dog](newDog("小狗"))
val c2 =newCovariant[SmallDog](newSmallDog("小狗",true))
var c3:Covariant[Animal]= c1 //狗赋值给Animal
var c4:Covariant[Animal]= c2
12.6 -A逆变
classCovariant[-T](t:T){
}//大的赋值给小的
val c1 =newCovariant[Dog](newDog("小狗"))
val c2 =newCovariant[SmallDog](newSmallDog("小狗",true))
var c3:Covariant[SmallDog]= c1
var c4:Covariant[Dog]= c2 //error
12.7 A不变
classCovariant[T](t:T){
}//强制
val c1 =newCovariant[Dog](newDog("小狗"))
val c2 =newCovariant[SmallDog](newSmallDog("小狗",true))
var c3:Covariant[SmallDog]= c1//error
var c4:Covariant[Dog]= c2 //error
var c5:Covariant[Dog]= c1
var c6:Covariant[SmallDog]= c2