暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Scala 学习 5:函数2+面向对象1

技术白小白 2019-06-07
269

Scala学习5

  • 函数

    • java异常处理特点

    • Scala异常处理

    • Scala异常小结

    • 惰性计算:尽可能延迟表达式求实,是许多函数是编程与语言的特性,惰性集合在需要时提供元素,无需预先计算。

    • java懒加载实现(懒汉式单例模式)

    • Scala原生支持实现惰性函数:返回值声明为lazy

        def main(args: Array[String]): Unit = {
      lazy val res = sum(1,3)
      println("----------")
      println("res = " + res)
      }

      def sum(n1:Int, n2:Int): Int = {
      println("sum() 执行了")
      n1 + n2
      }

      复制
    • 注意事项

    • 过程
      将函数返回值类型为Unit的函数称之过程

    • 惰性函数

    • 异常
      Scala异常处理使用try...catch,语法与Java类似。

  1. 使用try...catch...catch...finally的方式来处理异常

  2. 不管有没有捕获异常,finally块都会执行,一般用于释放资源

  3. Java将小范围异常写在前面,大范围异常写在后面,否则编译错误

  1. 在Scala中只有一个catch

  2. 在catch中有多个case,每个case可以匹配一种异常 case ex: ArithmeticException

  3. => 符号,表示后面对该异常的处理代码块

  4. finally最终执行

    def main(args: Array[String]): Unit = {
    try {
    val r = 10 /0
    } catch {
    case exception: ArithmeticException => {
    println("捕获了除数为0的算数异常")
    }
    case exception: Exception => println("捕获了异常")
    } finally {
    println("scala finally...")
    }
    }

    复制
  1. Scala异常的工作机制和Java一样,但Scala没有 "cheched(编译期)"异常,异常都在运行时捕获处理

  2. throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型,throw表达式的返回值是Nothing(所有类型的子类型)

     def main(args: Array[String]): Unit = {
    val res = test()
    println(res.toString())
    }

    def test(): Nothing = {
    throw new Exception("抛出异常")
    }

    复制
  3. 在Scala中,借用模式匹配的思想做异常匹配,所以,在Scala中使用一系列case子句来匹配异常

  4. case子句按次序捕获异常,通常把小范围异常写在前,大范围写在后,当然,反过来写也不会报错。

  5. Scala提供throw注解申明异常

     @throws(classOf[NumberFormatException])
    def f1() = {
    "abc".toInt
    }

    复制
  1. lazy不能修饰var类型的变量

  2. 在调用函数时,加了lazy会导致函数执行被推迟,在声明变量时,如果声明lazy,变量值分配也会被推迟, lazy val i = 0

  • Scala面向对象

    • 构造器属性

    • Bean属性 Scala字段加@BeanProperty时,会自动生成规范的getter/setter方法

        object BeanDemo {

      def main(args: Array[String]): Unit = {
      val car = new Car
      car.setName("hah")
      car.getName
      }
      }

      class Car{
      @BeanProperty var name : String = _
      }

      复制
    • Scala构造器包含主构造器和辅助构造器

        object ConDemo01 {
      def main(args: Array[String]): Unit = {
      val p1 = new Person("jack", 20)
      println(p1)
      }
      }

      /**
      * 主构造器
      * @param inName
      * @param inAge
      */
      class Person(inName: String, inAge: Int) {
      var name: String = inName
      var age: Int = inAge
      age += 1

      /**
      * 辅助构造器
      *
      * @param name
      */
      def this(name: String) {
      this("hah", 20)
      this.name = name
      }

      def this(age: Int){
      this("jack",age)
      this.age = age
      }

      println("执行~")

      override def toString: String = {
      this.name + " " + this.age
      }

      println(age)
      }

      复制
    • 调用机制原理

    • 注意

    • 与Java一样

    • 注意

    • Scala语言是面向对象的
      Java是面向对象的语言(java 还存在非面向对象:基本类型,null,静态方法等),Scala源自Java,所以也是面向对象的,是纯粹的面向对象,int为Int

    • 面向对象方式

      object CatDemo {
      def main(args: Array[String]): Unit = {
      val cat = new Cat

      // public void name_$eq(String x$1) { this.name = x$1; }
      cat.name = "小毕"
      cat.age = 10
      cat.color = "白色"
      }
      }

      class Cat{
      // 说明
      // 1. 当我们声明了var name: String时,在底层对应生成 private name
      // 2. 同时会生成两个public方法name() <=类似=> getter(), public name_$eq() => setter
      /**
      * public class Cat
      * {
      * private int age;
      * private String color;
      * private String name = ""; public String name() { return this.name; } public void name_$eq(String x$1) { this.name = x$1; }
      * public int age() { return this.age; } public void age_$eq(int x$1) { this.age = x$1; }
      * public String color() { return this.color; } public void color_$eq(String x$1) { this.color = x$1; }
      * }
      */
      var name: String = "" // 给初始值
      var age: Int = _ // _表示给默认值0
      var color:String = _ // _ 给默认值 ""
      }

      复制
    • 定义类

    • 属性
      与Java一样,可以是值类型,也可以是引用类型

    • 创建对象
      当创建的对象和new 对象有继承关系时,创建的对象必须写类型

        object CreateObj {
      def main(args: Array[String]): Unit = {
      val emp = new Emp
      // emp2 必须写类型 Person
      val emp2:Person = new Emp
      }
      }
      class Person{

      }
      class Emp extends Person{

      }

      复制
    • 类和对象的内存分配
      与Java相同

    • 方法

    • 构造器

    • 属性高级

    • Scala对象创建流程

    1. 加载类的信息(属性,方法)

    2. 在内存(堆)开辟空间

    3. 使用父类构造器(主/辅助构造器)进行初始

    4. 使用主构造器对属性进行初始化

    5. 使用辅助构造器对属性进行初始化

    6. 开辟对象的地址赋给引用

    1. Scala类的主构造器的形参未使用任何修饰符修饰,那么这个参数是局部变量

    2. 如果使用val关键字申明,那么Scala会将参数作为类的私有只读属性使用

    3. 如果使用var关键字申明,那么Scala会将参数作为成员属性,并提供对应的xxx()方法,即使这个属性是私有的,但也可以读写

    1. 辅助构造器函数名称为this,可以有多个,编译器通过不同的参数区分,底层就是Java构造器的重载, 辅助构造器必须第一行显示的调用主构造器

    2. Scala构造器与Java一样,完成对新对象的初始值,构造器没有返回值

    3. 主构造器的申明在类名之后

    4. 主构造器会执行类定义中的所有语句

    5. 上面的代码反编译后如下

      @ScalaSignature(bytes = "\006\001-3A!\004\b\0013!Aq\004\001B\001B\003%\001\005\003\005,\001\t\005\t\025!\003-\021\025y\003\001\"\0011\021\035)\004\0011A\005\002YBqa\016\001A\002\023\005\001\b\003\004?\001\001\006K\001\t\005\b\001\001\r\021\"\001A\021\035\t\005\0011A\005\002\tCa\001\022\001!B\023a\003\"B\030\001\t\003)\005\"B\030\001\t\0039\005\"B%\001\t\003R%A\002)feN|gN\003\002\020!\005Y1m\0348tiJ,8\r^8s\025\t\t\"#A\005dQ\006\004H/\032:1k)\0211\003F\001\006g\016\fG.\031\006\003+Y\taAY1z[VD(\"A\f\002\007\r|Wn\001\001\024\005\001Q\002CA\016\036\033\005a\"\"A\n\n\005ya\"AB!osJ+g-\001\004j]:\013W.\032\t\003C!r!A\t\024\021\005\rbR\"\001\023\013\005\025B\022A\002\037s_>$h(\003\002(9\0051\001K]3eK\032L!!\013\026\003\rM#(/\0338h\025\t9C$A\003j]\006;W\r\005\002\034[%\021a\006\b\002\004\023:$\030A\002\037j]&$h\bF\0022gQ\002\"A\r\001\016\0039AQaH\002A\002\001BQaK\002A\0021\nAA\\1nKV\t\001%\001\005oC6,w\fJ3r)\tID\b\005\002\034u%\0211\b\b\002\005+:LG\017C\004>\013\005\005\t\031\001\021\002\007a$\023'A\003oC6,\007%A\002bO\026,\022\001L\001\bC\036,w\fJ3r)\tI4\tC\004>\021\005\005\t\031\001\027\002\t\005<W\r\t\013\003c\031CQ!\016\006A\002\001\"\"!\r%\t\013}Z\001\031\001\027\002\021Q|7\013\036:j]\036$\022\001\t")
      public class Person
      {
      private String name;
      private int age;

      public String name() { return this.name; } public void name_$eq(String x$1) { this.name = x$1; }
      public int age() { return this.age; } public void age_$eq(int x$1) { this.age = x$1; }

      public Person(String name) {
      this("hah", 20);
      name_$eq(name);
      }

      public Person(int age) {
      this("jack", age);
      age_$eq(age);
      }

      public String toString() { return true.toString(); }

      public Person(String inName, int inAge) {
      // Byte code:
      // 0: aload_0
      // 1: invokespecial <init> : ()V
      // 4: aload_0
      // 5: aload_1
      // 6: putfield name : Ljava/lang/String;
      // 9: aload_0
      // 10: iload_2
      // 11: putfield age : I
      // 14: aload_0
      // 15: aload_0
      // 16: invokevirtual age : ()I
      // 19: iconst_1
      // 20: iadd
      // 21: invokevirtual age_$eq : (I)V
      // 24: getstatic scala/Predef$.MODULE$ : Lscala/Predef$;
      // 27: ldc '执行'
      // 29: invokevirtual println : (Ljava/lang/Object;)V
      // 32: getstatic scala/Predef$.MODULE$ : Lscala/Predef$;
      // 35: aload_0
      // 36: invokevirtual age : ()I
      // 39: invokestatic boxToInteger : (I)Ljava/lang/Integer;
      // 42: invokevirtual println : (Ljava/lang/Object;)V
      // 45: return
      // Line number table:
      // Java source line number -> byte code offset
      // #46 -> 0
      // #19 -> 4
      // #20 -> 9
      // #21 -> 14
      // #38 -> 24
      // #44 -> 32
      // #18 -> 45
      // Local variable table:
      // start length slot name descriptor
      // 0 46 0 this Lcom/baymux/scala/chapter05/constructor/Person;
      // 0 46 1 inName Ljava/lang/String;
      // 0 46 2 inAge I
      }
      }

      复制
    1. 当Scala开始执行时,现在栈区开辟一个main栈,main栈时最后被销毁的。

    2. 当Scala执行到一个方法时,总会开辟一个新的栈

    3. 每个栈时独立的空间,变量(基本数据类型)时独立的,相互不影响(引用类型除外)

    4. 当方法执行完毕后,该方法执行的栈就会被jvm回收

    1. Scala申明的属性必须给初始值

    2. 如果赋值为null,必须给属性类型

       var address = null // 引用时错误
      复制
    3. 如果定义属性时,不给默认值可以给_,系统会分配默认值

    1. Scala中,类不能申明为public,所有这些类都具有公有可见性

    2. 一个Scala源文件可以包含多个类,默认都是public


    文章转载自技术白小白,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论