Scala和Java的区别

Scala与java不同之处

1. 变量和常量

1.1 定义形式

  • java

    变量类型 名称 = 初始值;

    final 类型 名称 = 初始值:

  • scala

    var 名称 [: 类型] = 初始值 [ ;]

    val 名称 [: 类型] = 初始值 [ ; ]

    scala中var表示变量,val表示常量。引用类型的常量本身不能改变,带上引用对象的值可以改变。变量的类型可以省略不写,scala能自动推导类型,句尾的l;可选。

1.2 标识符的命名

除java原有规范外增加如下区别:

  1. 以操作符开头,且只包含操作符(+ - * / # !等)
  2. 使用反引号(``)包含的任意字符串,包括scala关键字。

2. 字符串输出

  1. 字符串拼接,使用+。

  2. 使用C语言类似格式化输出:printf(),%d整数,%f浮点数,%s字符串。

  3. 字符串模板(插值字符串):通过$获取变量值,println(s"字符串内容");

    scala中多行字符串的表示:“”“ 字符串

    ​ | 字符串

    ​ “”“.stripMargin

3. 键盘输入

java

Scanner in = new Scanner(System.in);
a=in.nextInt();         //输入整形数
b=in.nextInt(); 
c=in.nextLine();    //字符串

scala

val name = StdIn.readLine()  //字符串
val age = StdIn.readInt() 	//整数

4. 数据类型

scala取消了java的基本数据类型。其他类似java的包装类,Any为所有类的父类,Nothing为所有类的子类。

Unit 表示无值,类似于void,有有实例,写成()。Null 只有一个实例null,Null 可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)。

Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754 标准的单精度浮点数
Double 64 位 IEEE 754 标准的双精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

先贴一张官网的类型图

类型之间的转换

  • 低精度转高精度自动转,在有混合运算时。

  • 高精度转低精度需要强转。

    int a = (int)1.2         //java
    var num:Int = 1.2.toInt  //scala
    

5. 运算符

  • equals比较的是值是否相等
  • eq比较的是 地址是否相等
  • ,如果比较的对象是null,调用的是eq方法,如果比较的对象不是null,==调用的是equals方法
  • Scala 中没有++、--操作符,可以通过+=、-=来实现同样的效果;

6.分支 循环

6.1 分支

if、if...else...、if...else if ...else与java完全类似。

​ 另:Scala中的if else表达式其实是有返回值的,返回值取决于满足条件的最后一行代码,取所有分支共同的类祖先,该特性可以实现java的三元表达式,Scala本身没有三元表达式。

val res:String = if (age < 18) "童年" else "成年"

java中的switch-case在scala中通过模式匹配实现

 val x: Int = 5
    val y: String = x match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }

一目了然,最后的case_相当于java的default

6.2 循环

Scala中while、do...while 、for循环与java类似。

范围数据循环

  • to,前后均闭合。to是一个方法,scala是省略点,当只有一个参数时()也可省略
  for(i <- 1 to 10 [by 2] ){ // by 步长
      println(i)
   }

​ 等价于

for(i <- 1.to(10).by(2)){
      print(i+" ");
  }
  • until,前闭后开。
for(i <- 1 until 10) {
      println(i)
}

循环守卫

for(i <- 1 to 10 if i != 5) //排查特殊情况,满足守卫条件时执行循环。

循环嵌套

for (i <- 1 to 10;j <- 1 to i){
    print(i+"*"+j+"="+i*j)
 }

循环中断

​ Scala 内置控制结构特地去掉了 break continue,是为了更好的适应函数式编程,推

荐使用函数式的风格解决break和continue的功能。

1、循环守卫可以实现continue的功能。

 for (i <- 0 to 10 if i%2==0){
      println(i+" ")
    }

2、抛出异常实现continue的功能,在循环体内捕获异常使后面的代码不再执行。

 for(j <- 0 to 10 ){
      try{
        if(j%2 != 0){
          throw new RuntimeException;
        }
        println(j+" ")
      }catch {
        case ex: Exception =>
      }
 }

3、使用抛出异常的方式实现break的功能,在捕获异常后不做任何处理。

 try{
      for(i <- 0 to 5){
        if(i == 3){
          throw new RuntimeException
        }
        println(i);
      }
    }catch {
      case e:Exception=>{}
    }
    println("这是循环外的内容");

4、抛出异常使用try-catch太麻烦,可以使用Scala中的Breaks类的break方法,对可中断的代码块使用Breaks.breakable包含。

Breaks.breakable(
  for(i <- 0 to 5){
    if(i == 3){
      Breaks.break();
    }
    println(i);
  }
)

5、Scala是一门一切从简的编程语言,怎么结束个循环还要专门麻烦,当然可以简写

对引入Breaks类的时候引入Breaks下所有属性、方法,类似java的*

import scala.util.control.Breaks._
  breakable(
      for(i <- 0 to 5){
        if(i == 3){
         break();
        }
        println(i);
      }
    )
    println("这是循环外的内容");

7 函数式编程

7.1 函数的基本语法

def funName(x:Int,y:String):String={
     return s"${x}${y}";
  }

说明:

  • def 是定义函数的标识
  • funName是函数名称
  • x,y是参数名
  • x,y后的Int,String是x,y的类型
  • 括号后的String是函数返回类型,没有返回类型使用Unit,类似void,如果返回值为Unit,函数体内写了return也不起作用
  • {}内是函数体,有返回值是如果不写return会把最后一句表达式作为返回值。

7.2 函数中参数的特殊用法

7.2.1 可变参数

def f1(str:String*):Unit={
      println(str);
    }
f1("小明","小红");

如果有多个参数,可变参数放在最后

7.2.2参数默认值

def f2(name:String="小明"):Unit={
  println(s"hello ${name}");
}
f2("小红");
f2();

7.2.3 带名参数

def f3(age:Int,name:String):Unit = {
  println(s"${name}今年${age}岁了");
}
f3(20,"小明");
f3(name = "小红",age = 25);

带命参数在部分参数有默认值值是显得尤为重要。

def f3(age:Int=20,name:String):Unit = {
  println(s"${name}今年${age}岁了");
}
f3(20,"小明");
f3(name = "小红");

7.3 简化函数

下面懒人的福利来了,scala专门为懒人设计了能省就省的原则。

7.3.1retuen可以省略,函数体的最后一行代码会作为返回值。

def f1(name:String):String = {
   name;
}
println(f1("Jeck"))

7.3.2 如果函数体只有一行,{}可以省略

def f2(name:String):String = name;
println(f2("Jeck"))

7.3.3 如果返回类型可以推导出来,返回值类型可以省略

def f3(name:String) = name;
println(f3("Jeck"))

如果函数体有return,返回值类型不能省略。

7.3.4 如果函数没有返回值,等号可以省略。

def f4(name:String){
  println(name)
}
f4("Jeck4");

7.3.5 如果函数没有参数,调用时()可以省略

def f5(): Unit ={
  println("Hello")
}
f5;
f5();

7.3.5 如果函数没有参数,声明时()可以省略

def f6 {
    println("Hello")
 }
f6;

声明时省略的(),调用时就不能有();

7.4 匿名函数(lambda表达式)

定义形式

(name:String)=>{println(name);}

7.4.1 lambda表达式的调用方式

  1. 直接使用变量接收。

     var fun = (name:String) =>{println(name)}
      fun("小红");
    
  2. 作为参数

      def f2(func:String => Unit ):Unit={
          func("小红");
        }
    
        f2((name: String) => {println(name)})
    

7.4.2 匿名函数的简化

  1. 参数类型可以省略

    def f2(func:String => Unit ):Unit={
      func("小红");
    }
    f2((name) => {println(name)})
    
  2. 如果只有一个参数,()可以省略

    def f2(func:String => Unit ):Unit={
      func("小红");
    }
    f2(name => {println(name)})
    
  3. 函数体只有一行时,{}可以省略

    def f2(func:String => Unit ):Unit={
      func("小红");
    }
    f2(name => println(name))
    
  4. 如果参数只出现异常,参数可以省略,且在使用的地方使用_代替。

    def f2(func:String => Unit ):Unit={
      func("小红");
    }
    f2( println(_))
    
  5. 如果可以推断出当前传入的是一个函数体,可以直接省略下划线

    def f2(func:String => Unit ):Unit={
      func("小红");
    }
    f2(println)
    

7.5. 函数的高阶用法

7.5.1 函数作为值进行传递

def f1(name:String):Unit={
      println(s"hello ${name}")
 }
var f = f1 _; // 对函数名称加空格加下划线
var f2:String=>Unit=f1; //作用等同上一句
f2("小明");

7.5.2 函数作为参数传递

def arrayOperation(array:Array[Int],op:Int=>Int):Array[Int]={
  for(element <- array) yield op(element)
}

var arr:Array[Int] = Array(15,25,35);

def addOne(elem:Int):Int={
   elem+1;
}

val array:Array[Int] = arrayOperation(arr,addOne)
println(array.mkString(","));

8 面向对象

8.1 类的定义及创建

Scala中不需要像java一样类名和文件名相同,且必须是public修饰,Scala甚至一个文件下可以有多个类。

  1. 创建类和java使用相同的关键字class,Scala中没有public关键字,默认所有属性都是public的。

  2. 声明属性时可以指定访问权限,默认public,可以指定protected,private,protected不能在同包下访问。

  3. 一般可以直接使用对象.属性进行访问或赋值,如果一定要set,get方法可以在属性上添加@BeanProperty,会自动创建set,get

  4. 在定义时不需要指定属性具体值时,使用_,相当于占位符,会根据属性类型赋初始值。

    // 定义一个类
    class Student {
      // 定义属性
      private var name: String = "alice"
      @BeanProperty
      protected var age: Int = _
      var sex: String = _
    }
    
  5. 创建对象

    val student: Student = new Student()
    println(student.sex)
    println(student.age)//不能直接访问private的属性,protected的属性只在本身和子类中可以访问
    
  6. 特殊访问权限

    private[test] var age: Int = 18  // 可以指定在test包下可以访问属性
    

    8.2 构造方法

    8.2.1 主构造方法

    1. 定义类时在class后面增加参数及为构造函数,没有参数则为无参构造。

    2. 声明类时的参数使用var,或val定义,则会默认参数未类的属性,类体重无须重复定义。

      class Student(name: String, age: Int){
        def printInfo(){
          println(s"name = ${name}, age = $age")
        }
      }
      
      val student = new Student("小红", 20)
      student.printInfo()
      

    8.2.2 辅助构造器

    辅助构造器需要直接或间接调用主构造器。

    1、定义方式,辅助构造器的方法名必须为this。

    def this(name: String, age: Int, school: String){
        this(name, age)
        this.school = school
      }
    

    2、创建

    val student1 = new Student("小红", 25, "清华大学")
    

持续学习中.......
posted @ 2021-12-30 15:01  pu_xb  阅读(129)  评论(0编辑  收藏  举报