• 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, "清华大学")
      
    
    持续学习中.......
  • 相关阅读:
    poj2181 jumping cow
    poj2184
    POJ 1189 钉子和小球
    uva11019矩阵匹配器D316
    noip2015运输计划
    [LintCode] Last Position of Target
    [LintCode] K Closest Points
    [LintCode] K Closest Numbers In Sorted Array
    [LintCode] Closest Number in Sorted Array
    [LintCode] Perfect Squares
  • 原文地址:https://www.cnblogs.com/puxuebing/p/15748400.html
Copyright © 2020-2023  润新知