【Scala编程入门】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、Scala数据类型

1.各数据类型描述

在这里插入图片描述
在这里插入图片描述

2.使用细节

2.1 整型、浮点型、字符型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 Unit、Null、Nothing类型

//Null类只有一个实例对象null,类似于java中的null引用,null可以赋值给任意引用类型AnyRef,但是不能赋值给值类型AnyVal
//Unit类型用来标识过程,也就是没用明确返回值的函数,类似于java里的void。Unit类只有一个实例(),没有实质意义。
  def sayOk(): Unit = {
    println("ok")
  }
 //Nothing类可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回。该类是其他任意类型的子类,可以跟要求返回值的方法兼容。
 def test() : Nothing = {
 throw new Exception()
 }

二、Scala类

1.类与对象

1.1 属性/成员变量

在这里插入图片描述

package scalaDemo

object NullType {
  def main(args: Array[String]): Unit = {
    val cat = new Cat
    println(
      s"出生地:${cat.birthPlace}\n性别:${cat.gender}\n年龄:${cat.age}\n体重:${cat.height}\n是否可爱:${cat.isLovely}"
    )
  }
}

class Cat {
  var name: String = "狸花猫"
  var color: String = null
  var birthPlace = null     //Null类型,null为Null的一个实例
  var gender: String = _    //字符串类型默认值 null
  var age: Int = _    //Int类型默认值 0
  var height: Double = _  //Double类型默认值 0.0
  var isLovely: Boolean = _ //布尔类型默认值 false
}

1.2 对象的内存布局

在这里插入图片描述

1.3 方法和函数

程序调用方法过程
在这里插入图片描述

1.4 构造器

在这里插入图片描述
在这里插入图片描述
说明:
1.主构造器只有1个,辅助构造器方法名为this,可以有多个,编译器通过不同的参数类型来区分
在这里插入图片描述

package scalaDemo

object ConstractParam {
  def main(args: Array[String]): Unit = {
    val s = new Student2("sunny", "male", 28,172)
    println(s"${s.name}\n${s.gender}\n${s.age}")
  }
}

//1 主构造器的形参未加修饰符,这个参数为局部变量
//2 val修饰,这个参数会作为类的私有属性,只能读取
//3 var修饰,这个参数会作为类的私有属性,既能读取又能赋值
class Student2(inName: String, val inGender: String, var inAge: Int, inHeight: Double) {
  val name: String = inName
  val gender: String = inGender
  var age: Int = inAge
  var height: Double = _
}

反编译代码:

package scalaDemo;

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\001E3A!\001\002\001\013\tA1\013^;eK:$(GC\001\004\003%\0318-\0317b\t\026lwn\001\001\024\005\0011\001CA\004\013\033\005A!\"A\005\002\013M\034\027\r\\1\n\005-A!AB!osJ+g\r\003\005\016\001\t\005\t\025!\003\017\003\031IgNT1nKB\021qB\005\b\003\017AI!!\005\005\002\rA\023X\rZ3g\023\t\031BC\001\004TiJLgn\032\006\003#!A\001B\006\001\003\006\004%\taF\001\tS:<UM\0343feV\ta\002\003\005\032\001\t\005\t\025!\003\017\003%IgnR3oI\026\024\b\005\003\005\034\001\t\005\r\021\"\001\035\003\025Ig.Q4f+\005i\002CA\004\037\023\ty\002BA\002J]RD\001\"\t\001\003\002\004%\tAI\001\nS:\fu-Z0%KF$\"a\t\024\021\005\035!\023BA\023\t\005\021)f.\033;\t\017\035\002\023\021!a\001;\005\031\001\020J\031\t\021%\002!\021!Q!\nu\ta!\0338BO\026\004\003\002C\026\001\005\003\005\013\021\002\027\002\021%t\007*Z5hQR\004\"aB\027\n\0059B!A\002#pk\ndW\rC\0031\001\021\005\021'\001\004=S:LGO\020\013\006eQ*dg\016\t\003g\001i\021A\001\005\006\033=\002\rA\004\005\006-=\002\rA\004\005\0067=\002\r!\b\005\006W=\002\r\001\f\005\bs\001\021\r\021\"\001\030\003\021q\027-\\3\t\rm\002\001\025!\003\017\003\025q\027-\\3!\021\035i\004A1A\005\002]\taaZ3oI\026\024\bBB \001A\003%a\"A\004hK:$WM\035\021\t\017\005\003\001\031!C\0019\005\031\021mZ3\t\017\r\003\001\031!C\001\t\0069\021mZ3`I\025\fHCA\022F\021\0359#)!AA\002uAaa\022\001!B\023i\022\001B1hK\002B\021\"\023\001A\002\003\007I\021\001&\002\r!,\027n\0325u+\005a\003\"\003'\001\001\004\005\r\021\"\001N\003)AW-[4ii~#S-\035\013\003G9CqaJ&\002\002\003\007A\006\003\004Q\001\001\006K\001L\001\bQ\026Lw\r\033;!\001")
public class Student2 {
  private final String inGender;
  
  private int inAge;
  
  private final String name;
  
  private final String gender;
  
  private int age;
  
  private double height;
  
  public String inGender() {
    return this.inGender;
  }
  
  public int inAge() {
    return this.inAge;
  }
  
  public void inAge_$eq(int x$1) {
    this.inAge = x$1;
  }
  
  public Student2(String inName, String inGender, int inAge, double inHeight) {
    this.name = inName;
    this.gender = inGender;
    this.age = inAge();
  }
  
  public String name() {
    return this.name;
  }
  
  public String gender() {
    return this.gender;
  }
  
  public int age() {
    return this.age;
  }
  
  public void age_$eq(int x$1) {
    this.age = x$1;
  }
  
  public double height() {
    return this.height;
  }
  
  public void height_$eq(double x$1) {
    this.height = x$1;
  }
}

1.5 对象创建流程

在这里插入图片描述

1.6 scala包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo

object CompanionObject {
  def main(args: Array[String]): Unit = {
    val person = new Person()
    val student = new Student
    person.name = "鞠婧祎"  //person.name_$eq("鞠婧祎")
    person.gender2 = "女" //person.gender_$eq("女")
   // person.age = 26   //person.age_$eq(26)
    println(classOf[Person])
    println(person.getClass.getName)
  }
}
class Person {
  private val privateDescription: String = "私有属性-人类" //生成的字节码文件中,只有私有的getter方法--pirvate String privateDescription()
  val publicDescription: String = "公有属性-动物" //生成的字节码文件中,只有公有的getter方法--public String publicDescription()
  var name: String = _  //var修饰的变量,编译成的字节码文件中,既有setter方法又有getter方法
  protected var gender1: String = _ //当前类及其子类对象可以访问
  protected[scalaDemo] var gender2: String = _ //String和引用类型的变量,使用"_"初始化时全部为null
  private var age: Int = _  //val修饰的属性,字节码文件只有getter方法,而var修饰的属性,字节码文件既有setter又有getter方法
  println(Person.height) //访问伴生对象的私有属性--直接类名访问
}

object Person {
  private var height: Double = _
  private val person = new Person
  person.age //访问伴生类私有属性,需要先new一个对象
  //Person.age  //无法通过类名访问
}

class Student extends Person {
  private val person = new Person //子类中无法继承父类中的私有属性
}

/*
public class Person {
  private final String privateDescription = ";

  private String privateDescription() {
    return this.privateDescription;
  }

  private final String publicDescription = ";

  private String name;

  private String gender;

  private int age;

  public String publicDescription() {
    return this.publicDescription;
  }

  public String name() {
    return this.name;
  }

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

  public String gender() {
    return this.gender;
  }

  public void gender_$eq(String x$1) {
    this.gender = x$1;
  }

  private int age() {
    return this.age;
  }

  private void age_$eq(int x$1) {
    this.age = x$1;
  }
}
*/

2.类的继承

2.1 成员变量和成员方法的继承

package scalaDemo.extendsDemo.demo03

object ExtendsRelation {
  def main(args: Array[String]): Unit = {
    val son01 = new Son01
    val grandSon01 = new GrandSon01
    son01.sonInfo
    grandSon01.grandSonInfo
  }
}

//1.在scala中,子类继承了父类所有属性,但是private修饰的属性和方法在子类中无法访问,只能在本类和伴生对象中使用
//2.protected修饰的属性和方法在子类中可以访问
//3.protected,private修饰的除了上述位置,不能在同包的其他位置被访问
class Father01 {
  var name: String = "Lucy"
  protected var gender: String = "female"
  private var age: Int = 18

  def getBaseInfo = {
    println(s"name=$name gender=$gender age=$age")
  }

  protected def getJobInfo = {
    println("this is protected info...")
  }

  private def getSalaryInfo = {
    println("this is private info...")
  }
}

class Son01 extends Father01 {
  def sonInfo = {
    this.name = "LucySon01" //可访问--this.name_$eq("LucySon01")
    this.gender = "male" //可访问--this.gender_$eq("LucySon01")
    // this.age = 0  --无法访问
    println(s"Son01: ${this.name} ${this.gender}")
  }
}

class GrandSon01 extends Son01 {
  def grandSonInfo = {
    this.name = "LucyGrandSon01"
    this.gender = "male"
    // this.age = 0  --无法访问
    println(s"GrandSon01: ${this.name} ${this.gender}")
  }
}

2.2 重写方法

在这里插入图片描述

package scalaDemo.extendsDemo.demo03

object OverrideMethod {
  def main(args: Array[String]): Unit = {
    val son02 = new Son02
    son02.getInfo
  }
}

class Father02 {
  var name: String = "Lucy"

  def getInfo = {
    println(s"Father==$name")
  }

  def sayHello = {
    println("hello~~~")
  }
}

class Son02 extends Father02 {
  override def getInfo: Unit = {
    println(s"Son==$name")
    //子类中调用父类被重写的方法,使用supper
    super.getInfo
    //如果方法没有被重写,在子类中直接调用
    sayHello
  }
}

2.3 类型检查和转换

在这里插入图片描述

package scalaDemo.extendsDemo.demo03

object TypeConvert {
  def main(args: Array[String]): Unit = {
    val s1 = new Son03
    val s2 = new Son033
    convert(s1)
    convert(s2)
  }

  //父类的引用可以接收所有子类的引用--多态
  def convert(fa: Father03) = {
    if (fa.isInstanceOf[Son03]) {
      val son = fa.asInstanceOf[Son03]
      son.sonMethod
    } else if (fa.isInstanceOf[Son033]) {
      val son = fa.asInstanceOf[Son033]
      son.sonMethod
    } else {
      println(s"类型转换失败==${fa.getClass}")
    }
  }
}

class Father03 {
  val name = "father"

  def baseInfo = {
    println(s"name is $name")
  }

  def fatherMethod = {
    println(s"method is $name")
  }
}

class Son03 extends Father03 {
  val son03Name = "son03"

  override def baseInfo: Unit = {
    println(s"sonName is $son03Name")
  }

  def sonMethod = {
    println(s"method is $son03Name")
  }
}

class Son033 extends Father03 {
  val son033Name = "son033"

  override def baseInfo: Unit = {
    println(s"sonName is $son033Name")
  }

  def sonMethod = {
    println(s"method is $son033Name")
  }
}

2.4 超类的构造

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo.extendsDemo.demo03

object Constructor {
  def main(args: Array[String]): Unit = {
    /**
      * 执行流程:
      * 1.先调用子类辅助构造器this(height: Double)
      * 2.调用this即子类的主构造器,但是在初始化子类属性之前,必须先调用父类的主构造器
      * 3.调用父类this()即子类的辅助构造器,然后this("Lucy")即父类的主构造器
      * 4.输出结果
      * 父类-主构造器1...
      * 父类-主构造器2...
      * 父类-辅助构造器3...
      * 子类-主构造器1...
      * 子类-主构造器2...
      * 子类-辅助构造器...
      **/
    val son04 = new Son04(172)
  }
}

class Father04(inName: String) {
  var name: String = inName
  var age: Int = _
  var gender: String = _

  println("父类-主构造器1...")

  def this(inName: String, inAge: Int) = {
    this(inName)
    this.age = inAge //实际调用age_$eq(inAge);
    println("父类-辅助构造器1...")
  }

  def this(inName: String, inAge: Int, inGender: String) = {
    this(inName, inAge)
    this.gender = inGender //实际调用gender_$eq(inGender);
    println("父类-辅助构造器2...")
  }

  println("父类-主构造器2...")

  def this() = {
    this("Lucy") //调用主构造器
    println("父类-辅助构造器3...")
  }
}

class Son04() extends Father04() {
  var height: Double = _

  println("子类-主构造器1...")

  def this(height: Double) = {
    this
    this.height = height
    println("子类-辅助构造器...")
  }

  println("子类-主构造器2...")
}

反编译代码:

package scalaDemo.extendsDemo.demo03;

import scala.Predef$;
import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\001!2A!\001\002\001\023\t)1k\03481i)\0211\001B\001\007I\026lw\016M\032\013\005\0251\021aC3yi\026tGm\035#f[>T\021aB\001\ng\016\fG.\031#f[>\034\001a\005\002\001\025A\0211\002D\007\002\005%\021QB\001\002\t\r\006$\b.\032:1i!)q\002\001C\001!\0051A(\0338jiz\"\022!\005\t\003\027\001A\021b\005\001A\002\003\007I\021\001\013\002\r!,\027n\0325u+\005)\002C\001\f\032\033\0059\"\"\001\r\002\013M\034\027\r\\1\n\005i9\"A\002#pk\ndW\rC\005\035\001\001\007\t\031!C\001;\005Q\001.Z5hQR|F%Z9\025\005y\t\003C\001\f \023\t\001sC\001\003V]&$\bb\002\022\034\003\003\005\r!F\001\004q\022\n\004B\002\023\001A\003&Q#A\004iK&<\007\016\036\021\t\013=\001A\021\001\024\025\005E9\003\"B\n&\001\004)\002")
public class Son04 extends Father04 {
  private double height;
  
  public Son04() {
    Predef$.MODULE$.println(");
    Predef$.MODULE$.println(");
  }
  
  public double height() {
    return this.height;
  }
  
  public void height_$eq(double x$1) {
    this.height = x$1;
  }
  
  public Son04(double height) {
    this();
    height_$eq(height);
    Predef$.MODULE$.println(");
  }
}
package scalaDemo.extendsDemo.demo03;

import scala.Predef$;
import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\00153A!\001\002\001\023\tAa)\031;iKJ\004DG\003\002\004\t\0051A-Z7paMR!!\002\004\002\027\025DH/\0328eg\022+Wn\034\006\002\017\005I1oY1mC\022+Wn\\\002\001'\t\001!\002\005\002\f\0355\tABC\001\016\003\025\0318-\0317b\023\tyAB\001\004B]f\024VM\032\005\t#\001\021\t\021)A\005%\0051\021N\034(b[\026\004\"a\005\f\017\005-!\022BA\013\r\003\031\001&/\0323fM&\021q\003\007\002\007'R\024\030N\\4\013\005Ua\001\"\002\016\001\t\003Y\022A\002\037j]&$h\b\006\002\035=A\021Q\004A\007\002\005!)\021#\007a\001%!9\001\005\001a\001\n\003\t\023\001\0028b[\026,\022A\005\005\bG\001\001\r\021\"\001%\003!q\027-\\3`I\025\fHCA\023)!\tYa%\003\002(\031\t!QK\\5u\021\035I#%!AA\002I\t1\001\037\0232\021\031Y\003\001)Q\005%\005)a.Y7fA!IQ\006\001a\001\002\004%\tAL\001\004C\036,W#A\030\021\005-\001\024BA\031\r\005\rIe\016\036\005\ng\001\001\r\0211A\005\002Q\nq!Y4f?\022*\027\017\006\002&k!9\021FMA\001\002\004y\003BB\034\001A\003&q&\001\003bO\026\004\003\"C\035\001\001\004\005\r\021\"\001\"\003\0319WM\0343fe\"I1\b\001a\001\002\004%\t\001P\001\013O\026tG-\032:`I\025\fHCA\023>\021\035I#(!AA\002IAaa\020\001!B\023\021\022aB4f]\022,'\017\t\005\0065\001!\t!\021\013\0049\t\033\005\"B\tA\001\004\021\002\"\002#A\001\004y\023!B5o\003\036,\007\"\002\016\001\t\0031E\003\002\017H\021&CQ!E#A\002IAQ\001R#A\002=BQAS#A\002I\t\001\"\0338HK:$WM\035\005\0065\001!\t\001\024\013\0029\001")
public class Father04 {
  private String name;
  
  private int age;
  
  private String gender;
  
  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 gender() {
    return this.gender;
  }
  
  public void gender_$eq(String x$1) {
    this.gender = x$1;
  }
  
  public Father04(String inName, int inAge) {
    this(inName);
    age_$eq(inAge);
    Predef$.MODULE$.println(");
  }
  
  public Father04(String inName, int inAge, String inGender) {
    this(inName, inAge);
    gender_$eq(inGender);
    Predef$.MODULE$.println(");
  }
  
  public Father04() {
    this("Lucy");
    Predef$.MODULE$.println(");
  }
  
  public Father04(String inName) {
    this.name = inName;
    Predef$.MODULE$.println(");
    Predef$.MODULE$.println(");
  }
}

2.5 覆写字段

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public class JavaFieldOverride {
    public static void main(String[] args) {
        /**
         *总结:
         * 1.对于同一个对象,用父类的引用去取值(字段),会取到父类字段的值
         * 2.用子类的引用去取值(字段),则取到子类字段的值
         **/
        Sub s1 = new Sub();
        Super s2 = new Sub();
        System.out.println(s1.s); //输出sub
        System.out.println(((Super)s1).s); //输出super --通过强转,可以访问到父类被隐藏的字段
        System.out.println(s2.s); //输出super --通过父类引用,访问隐藏的字段
    }
}

class Super {
    String s = "super";
}

class Sub extends Super {
    String s = "sub";
}

2.6 动态绑定机制

public class JavaDynamicBind {
    public static void main(String[] args) {
        /**
         *java动态绑定机制:
         * 将一个子类对象地址,交给一个父类的引用:
         * 1.如果调用的是方法,则jvm机会将该方法和和对象的内存地址绑定
         * 2.如果调用的是属性,则没有动态绑定机制,在哪里调用,就返回对应值
         **/
        A a = new B();
        System.out.println(a.sum()); //输出20+10=30
        System.out.println(a.sum1()); //输出10+10=20
    }
}

class A {
    public int i = 10;

    public int sum() {
        return getI() + 10;
    }

    public int sum1() {
        return i + 10;
    }

    public int getI() {
        return i;
    }
}

class B extends A {
    public int i = 20;

//    public int sum() {
//        return i + 20;
//    }

    public int getI() {
        return i;
    }

//    public int sum1() {
//        return i + 10;
//    }
}
package scalaDemo.extendsDemo.demo03

object ScalaFieldOverride {
  def main(args: Array[String]): Unit = {
    val fa: Father05 = new Son05
    val son: Son05 = new Son05
    println(fa.name)  //fa.name() --动态绑定机制,实际调用子类的name()
    println(son.name) //son.name()
  }
}

class Father05 {
  val name = "Lucy" //public String name(){}
}

class Son05 extends Father05 {
  override val name: String = "sunny" //public String name(){}
}

反编译代码:

package scalaDemo.extendsDemo.demo03;

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\001\t2A!\001\002\001\023\tAa)\031;iKJ\004TG\003\002\004\t\0051A-Z7paMR!!\002\004\002\027\025DH/\0328eg\022+Wn\034\006\002\017\005I1oY1mC\022+Wn\\\002\001'\t\001!\002\005\002\f\0355\tABC\001\016\003\025\0318-\0317b\023\tyAB\001\004B]f\024VM\032\005\006#\001!\tAE\001\007y%t\027\016\036 \025\003M\001\"\001\006\001\016\003\tAqA\006\001C\002\023\005q#\001\003oC6,W#\001\r\021\005eqR\"\001\016\013\005ma\022\001\0027b]\036T\021!H\001\005U\0064\030-\003\002 5\t11\013\036:j]\036Da!\t\001!\002\023A\022!\0028b[\026\004\003")
public class Father05 {
  private final String name = "Lucy";
  
  public String name() {
    return this.name;
  }
}
package scalaDemo.extendsDemo.demo03;

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes = "\006\001\0052A!\001\002\001\023\t)1k\03481k)\0211\001B\001\007I\026lw\016M\032\013\005\0251\021aC3yi\026tGm\035#f[>T\021aB\001\ng\016\fG.\031#f[>\034\001a\005\002\001\025A\0211\002D\007\002\005%\021QB\001\002\t\r\006$\b.\032:1k!)q\002\001C\001!\0051A(\0338jiz\"\022!\005\t\003\027\001Aqa\005\001C\002\023\005C#\001\003oC6,W#A\013\021\005YabBA\f\033\033\005A\"\"A\r\002\013M\034\027\r\\1\n\005mA\022A\002)sK\022,g-\003\002\036=\t11\013\036:j]\036T!a\007\r\t\r\001\002\001\025!\003\026\003\025q\027-\\3!\001")
public class Son05 extends Father05 {
  private final String name = "sunny";
  
  public String name() {
    return this.name;
  }
}

2.7 覆写字段注意事项

在这里插入图片描述
在这里插入图片描述

package scalaDemo.extendsDemo.demo03

object ScalaFieldOverrideDetail {
  def main(args: Array[String]): Unit = {
  	val son = new Son06
  }
}

/**
  * 1.抽象字段(属性):就是没有初始化的字段
  * 2.当一个类中含有抽象属性时,则该类需要标记为abstract
  * 3.对于抽象的属性,在底层不会生成对应的属性声明(成员变量),而是生成两个对应的抽象方法(name()、name_$eq())
  **/
abstract class Father06 {
  var name: String  //抽象字段,可重写
  var age: Int = 99 //var非抽象属性,不能重写
}

/**
  * 说明:
  * 1.如果在子类中重写了父类的抽象属性,本质上是实现了抽象方法
  * 2.因此override也可以不写
  **/
class Son06 extends Father06 {
  override var name: String = "Lucy" //override可省略
  //override var age: Int = 18 //错误写法,因为var只能重写另一个抽象的var属性,否则运行会报错
}

反编译代码:

package scalaDemo.extendsDemo.demo03;

import scala.reflect.ScalaSignature;

public abstract class Father06 {
  private int age = 99;
  
  public abstract String name();
  
  public abstract void name_$eq(String paramString);
  
  public int age() {
    return this.age;
  }
  
  public void age_$eq(int x$1) {
    this.age = x$1;
  }
}
package scalaDemo.extendsDemo.demo03;

import scala.reflect.ScalaSignature;

public class Son06 extends Father06 {
  private String name = "Lucy";
  
  public String name() {
    return this.name;
  }
  
  public void name_$eq(String x$1) {
    this.name = x$1;
  }
}

2.8 抽象类

在这里插入图片描述

package scalaDemo.extendsDemo.demo03

object AbstractClass {
  def main(args: Array[String]): Unit = {
    //临时创建一个匿名子类
    val dog = new Animal02 {
      override var name: String = "dog"
      override var sex: String = "雌性"

      override def describ(): String = {
        s"name: $name\nsex: $sex"
      }

      override def action(): Unit = {
        println("正在追赶小偷...")
      }
    }

    val cat = new Animal02 {
      override var name: String = "cat"
      override var sex: String = "雄性"

      override def describ(): String = {
        s"name: $name\nsex: $sex"
      }

      override def action(): Unit = {
        println("正在抓老鼠...")
      }
    }

    println(dog.describ())
    dog.action()

    println(cat.describ())
    cat.action()
  }
}

abstract class Animal02 {
  var name: String //抽象属性
  var sex: String
  val name2 = "Animal01" //普通属性

  def describ(): String  //抽象方法
  def action()  //抽象方法

  /**
    * @Author: qwerdf@QAQ
    * @Description:
    * 总结:
    * 1.抽象类不能被实例化,可以通过创建匿名子类对象来实现
    * 2.抽象类不一定有abstract方法,但是含有抽象方法或抽象属性的一定是抽象类
    * 3.scala中抽象方法不能用abstract标记,定义方式:def temp()
    * 4.如果一个类继承了抽象类,则必须实现抽象类的所以抽象方法和抽象属性,除非它自己也声明为abstract类
    * 5.抽象方法和抽象属性不能使用private、final来修饰,因为这些关键字都是和重写/实现相违背的
    * 6.抽象类可以有实现的方法
    * 7.子类重写抽象方法不需要override,也可以加上
    * @Date: 2021/3/14
    * @Param null:
    * @return: null
    **/
}

2.9 匿名子类

在这里插入图片描述

3.内部类

3.1 基本使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 属性访问

4.伴生类与伴生对象

5.样例类

在这里插入图片描述

package scalaDemo

object CaseClassV1 {
  def main(args: Array[String]): Unit = {
    val arr = Array(
      Teacher01A("张三", 33), Teacher01A("李四", 26),
      Student01A("小明", 9), Student01A("小红", 19),
      Stranger01A
    )

    for (person <- arr) {
      println(matchCase(person))
    }
  }

  def matchCase(person: AnyRef) = {
    person match {
      case Teacher01A(name, age) => s"name=$name|age=$age 允许教师进入..."
      case Student01A(name, age) => {
        if (age < 18)
          s"name=$name|age=$age 允许未成年学生进入..."
        else
          s"name=$name|age=$age 允许成年学生进入..."
      }
      case Stranger01A => s"禁止陌生人进入!!!"
      case _ => s"错误类型匹配!!!"
    }
  }
}

/**
  * 1.case类是一种特殊的类,它们经过优化以被用于模式匹配,构造参数默认为val;
  * 2.当定义一个类时,如果在class关键字前加上case关键字,则该类称为case类;
  * 3.Scala为case类自动重载了许多实用的方法,包括toString、equals和hashcode方法;
  * 4.Scala为每一个case类自动生成一个伴生对象,其包括模板代码1个apply方法,
  * 因此,实例化case类的时候无需使用new关键字。和1个unapply方法,
  * 该方法包括一个类型为伴生类的参数返回的结果是Option类型,对应的类型参数是N元组,
  * N是伴生类中主构造器参数的个数。Unapply方法用于对对象进行解构操作,
  * 在case类模式匹配中,该方法被自动调用,并将待匹配的对象作为参数传递给它。
  **/

case class Teacher01A(name: String, age: Int)

case class Student01A(name: String, age: Int)

object Stranger01A

反编译代码:

package scalaDemo;

import scala.Function1;
import scala.Option;
import scala.Product;
import scala.Serializable;
import scala.Tuple2;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.ScalaRunTime$;
import scala.runtime.Statics;

public class Student01A implements Product, Serializable {
  private final String name;
  
  private final int age;
  
  public static Option<Tuple2<String, Object>> unapply(Student01A paramStudent01A) {
    return Student01A$.MODULE$.unapply(paramStudent01A);
  }
  
  public static Student01A apply(String paramString, int paramInt) {
    return Student01A$.MODULE$.apply(paramString, paramInt);
  }
  
  public static Function1<Tuple2<String, Object>, Student01A> tupled() {
    return Student01A$.MODULE$.tupled();
  }
  
  public static Function1<String, Function1<Object, Student01A>> curried() {
    return Student01A$.MODULE$.curried();
  }
  
  public String name() {
    return this.name;
  }
  
  public int age() {
    return this.age;
  }
  
  public Student01A copy(String name, int age) {
    return new Student01A(name, age);
  }
  
  public String copy$default$1() {
    return name();
  }
  
  public int copy$default$2() {
    return age();
  }
  
  public String productPrefix() {
    return "Student01A";
  }
  
  public int productArity() {
    return 2;
  }
  
  public Object productElement(int x$1) {
    int i = x$1;
    switch (i) {
      default:
        throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
      case 1:
      
      case 0:
        break;
    } 
    return name();
  }
  
  public Iterator<Object> productIterator() {
    return ScalaRunTime$.MODULE$.typedProductIterator(this);
  }
  
  public boolean canEqual(Object x$1) {
    return x$1 instanceof Student01A;
  }
  
  public int hashCode() {
    int i = -889275714;
    i = Statics.mix(i, Statics.anyHash(name()));
    i = Statics.mix(i, age());
    return Statics.finalizeHash(i, 2);
  }
  
  public String toString() {
    return ScalaRunTime$.MODULE$._toString(this);
  }
  
  public boolean equals(Object x$1) {
    // Byte code:
    //   0: aload_0
    //   1: aload_1
    //   2: if_acmpeq -> 92
    //   5: aload_1
    //   6: astore_2
    //   7: aload_2
    //   8: instanceof scalaDemo/Student01A
    //   11: ifeq -> 19
    //   14: iconst_1
    //   15: istore_3
    //   16: goto -> 21
    //   19: iconst_0
    //   20: istore_3
    //   21: iload_3
    //   22: ifeq -> 96
    //   25: aload_1
    //   26: checkcast scalaDemo/Student01A
    //   29: astore #4
    //   31: aload_0
    //   32: invokevirtual name : ()Ljava/lang/String;
    //   35: aload #4
    //   37: invokevirtual name : ()Ljava/lang/String;
    //   40: astore #5
    //   42: dup
    //   43: ifnonnull -> 55
    //   46: pop
    //   47: aload #5
    //   49: ifnull -> 63
    //   52: goto -> 88
    //   55: aload #5
    //   57: invokevirtual equals : (Ljava/lang/Object;)Z
    //   60: ifeq -> 88
    //   63: aload_0
    //   64: invokevirtual age : ()I
    //   67: aload #4
    //   69: invokevirtual age : ()I
    //   72: if_icmpne -> 88
    //   75: aload #4
    //   77: aload_0
    //   78: invokevirtual canEqual : (Ljava/lang/Object;)Z
    //   81: ifeq -> 88
    //   84: iconst_1
    //   85: goto -> 89
    //   88: iconst_0
    //   89: ifeq -> 96
    //   92: iconst_1
    //   93: goto -> 97
    //   96: iconst_0
    //   97: ireturn
    // Line number table:
    //   Java source line number -> byte code offset
    //   #44	-> 0
    // Local variable table:
    //   start	length	slot	name	descriptor
    //   0	98	0	this	LscalaDemo/Student01A;
    //   0	98	1	x$1	Ljava/lang/Object;
  }
  
  public Student01A(String name, int age) {
    Product.class.$init$(this);
  }
}
package scalaDemo;

import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.Tuple2;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;

public final class Student01A$ extends AbstractFunction2<String, Object, Student01A> implements Serializable {
  public static final Student01A$ MODULE$;
  
  public final String toString() {
    return "Student01A";
  }
  
  public Student01A apply(String name, int age) {
    return new Student01A(name, age);
  }
  
  public Option<Tuple2<String, Object>> unapply(Student01A x$0) {
    return (x$0 == null) ? (Option<Tuple2<String, Object>>)scala.None$.MODULE$ : (Option<Tuple2<String, Object>>)new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age())));
  }
  
  private Object readResolve() {
    return MODULE$;
  }
  
  private Student01A$() {
    MODULE$ = this;
  }
}

三、特质trait

1.动态混入

在这里插入图片描述

package scalaDemo.traitDemo

object MixInTraitV1 {
  def main(args: Array[String]): Unit = {
/**
  * 说明:
  * 1.定义关键字trait。特质类似于java中的接口,java中实现接口关键字"implements",scala中使用"with"
  *   如class A extends classB with traitC with traitD …
  **/
    val sql03 = new MySql03 with Oper03
    val sql04 = new MySql04 with Oper03
    //如果抽象类中有抽象方法,需要实现
    val sql05 = new MySql05 with Oper03 {
      override def insert(num: Double): Unit = {
        println(s"插入数据: $num")
      }
    }
    sql03.delete(3.14)
    sql04.delete(6.28)
    sql05.insert(9.42)
  }
}

trait Oper03 {
  def delete(num: Double) = {
    println(s"删除数据: $num")
  }
}

class MySql03 {

}

abstract class MySql04 {

}

abstract class MySql05 {
  def insert(num: Double)
}

2. 叠加特质

在这里插入图片描述
在这里插入图片描述

package scalaDemo.traitDemo

object MixInTraitV2 {
  def main(args: Array[String]): Unit = {
    /**
      * 说明:
      * 动态混入对象时,初始化顺序
      * 1.Oper06A...
      * 2.Oper06B...
      * 3.Oper06C1...
      * 4.Oper06C2...
      *
      * 调用delete方法执行顺序
      * 1.Oper06C2-删除数据:3.14
      * 2.Oper06C1-删除数据:3.14
      * 3.Oper06B-删除数据:3.14
      **/
    val sql06 = new MySql06 with Oper06C1 with Oper06C2
    println("======================================")
    sql06.delete(3.14)
  }
}

class MySql06 {

}

trait Oper06A {
  println("Oper06A...")

  def delete(num: Double)
}

trait Oper06B extends Oper06A { //特质,继承Oper06A
  println("Oper06B...")

  //实现或重写Oper06A中的抽象方法,override可省略
  override def delete(num: Double): Unit = {
    println(s"Oper06B-删除数据:$num")
  }
}

trait Oper06C1 extends Oper06B {
  println("Oper06C1...")

  //由于Oper06B中已经实现delete方法,这里只能是重写,override不能省略
  override def delete(num: Double): Unit = {
    println(s"Oper06C1-删除数据:$num")
    //动态混入时,这里不一定调用的是父类Oper06B中的方法
    //得看混入顺序--new MySql06 with Oper06C1 with Oper06C2
    super.delete(num)
  }
}

trait Oper06C2 extends Oper06B {
  println("Oper06C2...")

  override def delete(num: Double): Unit = {
    println(s"Oper06C2-删除数据:$num")
    //动态混入时,这里不一定调用的是父类Oper06B中的方法
    //得看混入顺序--new MySql06 with Oper06C1 with Oper06C2
    super.delete(num)
    //可以指定具体类型,从而访问到Oper06B中的delete方法
    //super[Oper06B].delete(num)
    //super[Oper06A].delete(num)  执行报错,因为Oper06A不是当前特质的直接父特质(超类)
  }
}

3.富接口

在这里插入图片描述

4.特质中的字段

在这里插入图片描述
在这里插入图片描述

package scalaDemo.traitDemo

object MixInTraitV3 {
  def main(args: Array[String]): Unit = {
    val sql07 = new MySql07 with Oper07 {
      override var oper_date: String = _
    }
  }
}

class MySql07 {

}

trait Oper07 {
  val num: Int = 66  
  var oper_type: String = "insert"
  var oper_date: String  //抽象字段
  def insert() = {

  }
}

反编译代码:

package scalaDemo.traitDemo;

import scala.runtime.TraitSetter;

public final class MixInTraitV3$ {
  public static final MixInTraitV3$ MODULE$;
  
  public void main(String[] args) {
    MySql07 sql07 = new MixInTraitV3$$anon$1();
  }
  
  public final class MixInTraitV3$$anon$1 extends MySql07 implements Oper07 {
    private String oper_date;
    
    private final int num;
    
    private String oper_type;
    
    public int num() {
      return this.num;
    }
    
    public String oper_type() {
      return this.oper_type;
    }
    
    @TraitSetter
    public void oper_type_$eq(String x$1) {
      this.oper_type = x$1;
    }
    
    public void scalaDemo$traitDemo$Oper07$_setter_$num_$eq(int x$1) {
      this.num = x$1;
    }
    
    public void insert() {
      Oper07$class.insert(this);
    }
    
    public MixInTraitV3$$anon$1() {
      Oper07$class.$init$(this);
    }
    
    public String oper_date() {
      return this.oper_date;
    }
    
    public void oper_date_$eq(String x$1) {
      this.oper_date = x$1;
    }
  }
  
  private MixInTraitV3$() {
    MODULE$ = this;
  }
}

5.特质构造顺序

在这里插入图片描述
在这里插入图片描述

package scalaDemo.traitDemo

object MixInTraitV4 {
  def main(args: Array[String]): Unit = {
    /**
      * 说明:
      * 声明类时混入特质,即静态混入,初始化顺序
      * class MySql08B extends MySql08A with Oper08C1 with Oper08C2
      * 1.MySql08A...
      * 2.Oper08A...
      * 3.Oper08B...
      * 4.Oper08C1...
      * 5.Oper08C2...
      * 6.MySql08B...
      *
      * 动态混入特质,初始化顺序
      * new MySql08C with Oper08C1 with Oper08C2
      * 1.MySql08A...
      * 2.MySql08C...
      * 3.Oper08A...
      * 4.Oper08B...
      * 5.Oper08C1...
      * 6.Oper08C2...
      *
      * 调用delete方法执行顺序
      * 1.Oper08C2-删除数据:3.14
      * 2.Oper08C1-删除数据:3.14
      * 3.Oper08B-删除数据:3.14
      * 
      * 1.Oper08C2-删除数据:6.28
      * 2.Oper08C1-删除数据:6.28
      * 3.Oper08B-删除数据:6.28
      **/
    val sql08b = new MySql08B
    println("===================================")
    //动态混入
    val sql08c = new MySql08C with Oper08C1 with Oper08C2
    println("===================================")

    //调用方法执行顺序
    sql08b.delete(3.14)
    println("===================================")
    sql08c.delete(6.28)
  }
}

class MySql08A {
  println("MySql08A...")
}

class MySql08B extends MySql08A with Oper08C1 with Oper08C2 {
  println("MySql08B...")
}

class MySql08C extends MySql08A {
  println("MySql08C...")
}

trait Oper08A {
  println("Oper08A...")

  def delete(num: Double)
}

trait Oper08B extends Oper08A {
  println("Oper08B...")

  override def delete(num: Double): Unit = {
    println(s"Oper08B-删除数据:$num")
  }
}

trait Oper08C1 extends Oper08B {
  println("Oper08C1...")

  override def delete(num: Double): Unit = {
    println(s"Oper08C1-删除数据:$num")
    super.delete(num)
  }
}

trait Oper08C2 extends Oper08B {
  println("Oper08C2...")

  override def delete(num: Double): Unit = {
    println(s"Oper08C2-删除数据:$num")
    super.delete(num)
  }
}

6.扩展类的特质

在这里插入图片描述

7.自身类型

在这里插入图片描述

四、隐式转换

1.隐式函数

在这里插入图片描述

package scalaDemo.implicitDemo.implicitFunction

object ImplicitFuncV1 {
  def main(args: Array[String]): Unit = {
    //底层编译成double2Int$1(double d)
    implicit def double2Int(d: Double) = {
      d.toInt
    }
    val num: Int = 3.14  //double2Int$1(3.14)
  }
}

反编译代码:

package scalaDemo.implicitDemo.implicitFunction;

public final class ImplicitFuncV1$ {
  public static final ImplicitFuncV1$ MODULE$;
  
  private final int double2Int$1(double d) {
    return (int)d;
  }
  
  public void main(String[] args) {
    int num = double2Int$1(3.14D);
  }
  
  private ImplicitFuncV1$() {
    MODULE$ = this;
  }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo.implicitDemo.implicitFunction

object ImplicitFuncV2 {

  implicit def addDelete(mysql: MySql01) = {
    new Oper01
  }

  def main(args: Array[String]): Unit = {

//    implicit def addDelete(mysql: MySql01) = {
//      new Oper01
//    }
    val sql = new MySql01
    sql.insert(9)
    /**
     * 说明:
      * 1.当隐式函数定义在main方法内时: addDelete$1(sql).delete(10)
      * 2.当隐式函数定义在main方法外时: addDelete(sql).delete(10)
     **/

    sql.delete(10)
  }
}

class MySql01 {
  def insert(num: Int) = {
    println(s"插入数据:$num")
  }
}

class Oper01 {
  def delete(num: Int) = {
    println(s"删除数据: $num")
  }
}

反编译代码:

package scalaDemo.implicitDemo.implicitFunction;

public final class ImplicitFuncV2$ {
  public static final ImplicitFuncV2$ MODULE$;
  
  public Oper01 addDelete(MySql01 mysql) {
    return new Oper01();
  }
  
  public void main(String[] args) {
    MySql01 sql = new MySql01();
    sql.insert(9);
    addDelete(sql).delete(10);
  }
  
  private ImplicitFuncV2$() {
    MODULE$ = this;
  }
}

2.隐式值

在这里插入图片描述

package scalaDemo.implicitDemo.implicitValue

object ImplicitValueV1 {
  def main(args: Array[String]): Unit = {
    implicit val name: String = "Lucy" //隐式值

    //底层函数名:showInfo$1
    def showInfo(implicit inName: String) = {
      println(s"name is $inName")

      //showInfo$2
      def showInfo() = {
        println("main -> showInfo -> showInfo")
      }
    }
    showInfo
  }

  //showInfo
  def showInfo() = {
    println("object -> showInfo")
  }
}

反编译代码:

package scalaDemo.implicitDemo.implicitValue;

import scala.StringContext;
import scala.collection.Seq;

public final class ImplicitValueV1$ {
  public static final ImplicitValueV1$ MODULE$;
  
  public void main(String[] args) {
    String name = "Lucy";
    showInfo$1(name);
  }
  
  private final void showInfo$1(String inName) {
    (new String[2])[0] = "name is ";
    (new String[2])[1] = "";
    scala.Predef$.MODULE$.println((new StringContext((Seq)scala.Predef$.MODULE$.wrapRefArray((Object[])new String[2]))).s((Seq)scala.Predef$.MODULE$.genericWrapArray(new Object[] { inName })));
  }
  
  private final void showInfo$2() {
    scala.Predef$.MODULE$.println("main -> showInfo -> showInfo");
  }
  
  public void showInfo() {
    scala.Predef$.MODULE$.println("object -> showInfo");
  }
  
  private ImplicitValueV1$() {
    MODULE$ = this;
  }
}

package scalaDemo.implicitDemo.implicitValue

object ImplicitValueV2 {
  def main(args: Array[String]): Unit = {
    implicit val name: String = "Lucy"
   // implicit val name2: String = "Lucy2"  不能有两个相同类型的隐式值,否则编译器会无法识别

    /***
     * 说明
      * 1.隐式值优先级:传值 > 隐式值 > 默认值
      * 2.隐式值匹配时不能有二义性
      * 3.如果调用方法时,传值、隐式值、默认值都没有,程序会报错
     **/
    showInfo1  //输出Lucy
    showInfo1("@sunny") //输出@sunny
    showInfo2 //输出18
    //showInfo3//不传值会报错
  }

  def showInfo1(implicit inName: String = "sunny")= {
    println(s"name is $inName")
  }

  def showInfo2(implicit inAge: Int = 18) = {
    println(s"age is $inAge")
  }

  def showInfo3(implicit inAge: Int) = {
    println(s"age is $inAge")
  }
}

反编译代码:

package scalaDemo.implicitDemo.implicitValue;

import scala.StringContext;
import scala.collection.Seq;
import scala.runtime.BoxesRunTime;

public final class ImplicitValueV2$ {
  public static final ImplicitValueV2$ MODULE$;
  
  public void main(String[] args) {
    String name = "Lucy";
    showInfo1(name);
    showInfo1("@sunny");
    showInfo2(showInfo2$default$1());
  }
  
  public String showInfo1$default$1() {
    return "sunny";
  }
  
  public void showInfo1(String inName) {
    (new String[2])[0] = "name is ";
    (new String[2])[1] = "";
    scala.Predef$.MODULE$.println((new StringContext((Seq)scala.Predef$.MODULE$.wrapRefArray((Object[])new String[2]))).s((Seq)scala.Predef$.MODULE$.genericWrapArray(new Object[] { inName })));
  }
  
  public int showInfo2$default$1() {
    return 18;
  }
  
  public void showInfo2(int inAge) {
    (new String[2])[0] = "age is ";
    (new String[2])[1] = "";
    scala.Predef$.MODULE$.println((new StringContext((Seq)scala.Predef$.MODULE$.wrapRefArray((Object[])new String[2]))).s((Seq)scala.Predef$.MODULE$.genericWrapArray(new Object[] { BoxesRunTime.boxToInteger(inAge) })));
  }
  
  public void showInfo3(int inAge) {
    (new String[2])[0] = "age is ";
    (new String[2])[1] = "";
    scala.Predef$.MODULE$.println((new StringContext((Seq)scala.Predef$.MODULE$.wrapRefArray((Object[])new String[2]))).s((Seq)scala.Predef$.MODULE$.genericWrapArray(new Object[] { BoxesRunTime.boxToInteger(inAge) })));
  }
  
  private ImplicitValueV2$() {
    MODULE$ = this;
  }
}

3.隐式类

在这里插入图片描述

package scalaDemo.implicitDemo.implicitClass

object ImplicitClassV1 {
  def main(args: Array[String]): Unit = {

    /***
      *说明:
      * implicit关键字声明一个class后,对应底层编译生成Oper02$1()方法,并返回隐式类ImplicitClassV1$Oper02$2
      * private final ImplicitClassV1$Oper02$2 Oper02$1(MySql02 mysql) {
      *   return new ImplicitClassV1$Oper02$2(mysql);
      * }
      * 
      *总结:
      * 1.隐式类的构造参数有且只能有一个
      * 2.隐式类必须定义在类、伴生对象、包对象里面,不能是顶级的objects
      * 3.隐式类不能是case class
      * 4.作用域内不能有同名标识符,否则编译器无法识别
     **/
    implicit class Oper02(val mysql: MySql02) {
      def delete(sql: MySql02) = {
        println(s"delete num: ${sql.num}")
      }
    }

    val sql02 = new MySql02
    sql02.insert()
    sql02.delete(sql02) //Oper02$1(sql02).delete(sql02)

  }
//  implicit class Oper02(val mysql: MySql02) {
//    def delete(sql: MySql02) = {
//      println(s"delete num: ${sql.num}")
//    }
//  }
}

class MySql02 {
  val num = 3.14
  def insert(num2: Double = 6.28) = {
    println(s"insert num: $num2")
  }
}

反编译代码:

package scalaDemo.implicitDemo.implicitClass;

public final class ImplicitClassV1$ {
  public static final ImplicitClassV1$ MODULE$;
  
  private final ImplicitClassV1$Oper02$2 Oper02$1(MySql02 mysql) {
    return new ImplicitClassV1$Oper02$2(mysql);
  }
  
  public void main(String[] args) {
    MySql02 sql02 = new MySql02();
    sql02.insert(sql02.insert$default$1());
    Oper02$1(sql02).delete(sql02);
  }
  
  private ImplicitClassV1$() {
    MODULE$ = this;
  }
}

上述生成的隐式类ImplicitClassV1$Oper02$2结构可参考下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、集合

1.集合基本介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.数组

2.1 定长数组

在这里插入图片描述
在这里插入图片描述
1)定义方式

//通过new的方式
val arr1 = new Array [Int] (3)  //指定长度为3。Int类型初始化为0
val arr2 = new Array [String] (3) //String类型初始化为null
//通过apply方法
//apply方法内部通过new Array [T] ()
val arr3 = Array(1,"scala",3,14)
val arr4 = Array.apply(1,"scala",3,14*2)

2)定长数组赋值、修改

//通过下标赋值、修改值
arr2(0) = "章子怡"
arr2(1) = "王菲"
arr2(1) = "鞠婧祎"
//返回:ArrayBuffer(章子怡, 鞠婧祎, null)

3)数组转List

val list1: immutable.Seq[String] = arr2.toList
val list2: List[String] = arr2.toList

4)遍历数组元素

//通过下标取值
for (i <- 0 until arr3.length) {
  println(s"$i==${arr4(i)}")
}
//直接循环出数组元素
for (i <- arr4) {
  println(i)
}
//foreach方式
arr03.foreach {
  x => println(x)
}
package scalaDemo.collectionDemo.array

object ArrayV1 {
  def main(args: Array[String]): Unit = {
    //通过new的方式
    val arr01 = new Array[Any](3)
    arr01(0) = "Lucy"
    arr01(1) = "sunny"

    //通过apply方法
    val arr02 = Array("Lucy","sunny",3.14)
    val arr03 = Array.apply("@Lucy","@sunny",3.14*2)

    //直接循环出数组元素
    for (elem <- arr01) {
      println(elem)
    }
    println("===========================")
    //通过下标取值
    for (i <- 0 until arr02.length) {
      println(arr02(i))
    }
    println("===========================")
    //foreach方式
    arr03.foreach {
      x => println(x)
    }

  }
}

2.2 变长数组

在这里插入图片描述
1)定义方式

//需要引入mutable下面的包
import scala.collection.mutable.{ArrayBuffer, ListBuffer} 
//通过new的方式
val buffer1 = new ArrayBuffer[String] ()
buffer1 += "王祖贤"
buffer1 += "林青霞"
//通过apply方法
val buffer2 = ArrayBuffer("赵丽颖","鞠婧祎")
val buffer3 = ArrayBuffer.apply("李一桐","周迅")

2)添加元素

    //添加多种类型元素
    arr03.append("@sunny",("@Lucy",18))
    arr03 += (3.14*2,3.14*3,("@Lucy",19))

3)删除元素

buffer3.remove(1) //删除下标为1的元素

4)遍历元素

    //遍历元素
    //方式1
    for (elem <- arr01) {
      println(elem)
    }
    println("==========================")
    //方式2
    for (i <- 0 until arr02.length) {
      println(arr02(i))
    }
    println("==========================")
    //方式3
    arr03.foreach {
      x => println(x)
    }

5)排序

val buffer4 = ArrayBuffer(1,3,5,7,6,4,2,0)
val buffer4_1 = buffer4.sortWith(_<_)
val buffer4_2 = buffer4.sortWith((x,y) => x < y)
package scalaDemo.collectionDemo.array

import scala.collection.mutable.ArrayBuffer

object ArrayV2 {
  def main(args: Array[String]): Unit = {
    //通过new的方式
    val arr01 = new ArrayBuffer[Any]()
    //添加元素
    arr01.append("Lucy")
    arr01 += "sunny"

    通过apply方法
    val arr02 = ArrayBuffer("Lucy","sunny",3.14)
    val arr03 = ArrayBuffer.apply("@Lucy","@sunny",3.14*2)

    //遍历元素
    //方式1
    for (elem <- arr01) {
      println(elem)
    }
    println("==========================")
    //方式2
    for (i <- 0 until arr02.length) {
      println(arr02(i))
    }
    println("==========================")
    //方式3
    arr03.foreach {
      x => println(x)
    }
  }
}

在这里插入图片描述

2.3 定长数组与变长数组的转换

在这里插入图片描述

package scalaDemo.collectionDemo.array

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object ArrayV3 {
  def main(args: Array[String]): Unit = {
    val arr01 = Array("Lucy","sunny")
    val arr02 = new ArrayBuffer[Any]()
    arr02.append("@Lucy","@sunny")

    //定长转变长数组
    //底层new mutable.ArrayBuffer[A1](size)
    val arr03: mutable.Buffer[Any] = arr01.toBuffer
    //添加多种类型元素
    arr03.append("@sunny",("@Lucy",18))
    arr03 += (3.14*2,3.14*3,("@Lucy",19))

    //变长转定长数组
    //底层new Array[B](size)
    val arr04: Array[Any] = arr02.toArray

    arr03.foreach(println(_))
    println("=========================")
    arr04.foreach(println(_))
  }
}

2.4 多维数组

在这里插入图片描述

2.5 Java的List转Scala数组

在这里插入图片描述

3.元组

在这里插入图片描述

package scalaDemo.collectionDemo.tuple

object TupleV1 {
  def main(args: Array[String]): Unit = {
    //创建
    //tuple01是一个Tuple,类型是Tuple4
    val tuple01: (String, String, Int, Int) = ("Lucy","sunny",18,19)
  }
}

反编译代码:

package scalaDemo.collectionDemo.tuple;

import scala.Tuple4;
import scala.runtime.BoxesRunTime;

public final class TupleV1$ {
  public static final TupleV1$ MODULE$;
  
  public void main(String[] args) {
    Tuple4 tuple01 = new Tuple4("Lucy", "sunny", BoxesRunTime.boxToInteger(18), BoxesRunTime.boxToInteger(19));
  }
  
  private TupleV1$() {
    MODULE$ = this;
  }
}

在这里插入图片描述

package scalaDemo.collectionDemo.tuple

object TupleV1 {
  def main(args: Array[String]): Unit = {
    //创建
    //tuple01是一个Tuple,类型是Tuple4
    val tuple01: (String, String, Int, Int) = ("Lucy","sunny",18,19)

    //访问元素
    //根据顺序号--第一个元素
    println(tuple01.productElement(0))

    //根据索引--第一个元素
    /**
      * 底层实现:scala.Product4中的方法,含有Product1~Product22
      * 具体根据元组的类型去调用哪个Product中的方法,这里为scala.Product4
      * override def productElement(n: Int) = n match {
      * case 0 => _1
      * case 1 => _2
      * case 2 => _3
      * case 3 => _4
      * case _ => throw new IndexOutOfBoundsException(n.toString())
      * }
     **/
    tuple01.productElement(0)
  }
}

在这里插入图片描述

    //遍历元组
    val tuple02 = ("@Lucy","@sunny",3.14)
    val iterator: Iterator[Any] = tuple02.productIterator
    for (item <- iterator) {
      println(item)
    }

4.列表List

4.1 不可变List

在这里插入图片描述
在这里插入图片描述
1)定义方式

    //创建
    val lis01 = List("Lucy","sunny",18,19)
    val lis02 = Nil //表示一个空集合List()

2)元素访问

    //访问List元素
    val lis03 = List("@Lucy","@sunny",18,19,20)
    println(lis03(0)) //索引从0开始,取出第一个元素

3)元素追加
在这里插入图片描述
在这里插入图片描述

    //追加元素--生成新List,原集合不变
    //方式1 :+
    val lis04 = List("A","B","C")
    val lis05 = lis04 :+ "Lucy"  //在列表最后追加元素
    //方式2 +:
    val lis06 = "sunny" +: lis04 //在列表前边追加元素
    println(lis04) //List(A, B, C)
    println(lis05) //List(A, B, C, Lucy)
    println(lis06) //List(sunny, A, B, C)

    //方式3 :: 
    val lis07 = List("A","B","C")
    //向一个空列表添加元素
    val lis08 = 1::2::3::lis07::Nil
    println(lis08) //List(1, 2, 3, List(A, B, C))

    //方式4 :::  该符号左右必须是集合才能使用
    //将集合中的每一个元素添加到空集合
    val lis09 = 1::2::3::lis07:::Nil
    println(lis09) //List(1, 2, 3, A, B, C)

4.2 可变List

在这里插入图片描述

package scalaDemo.collectionDemo.list

import scala.collection.mutable.ListBuffer

object ListV2 {
  def main(args: Array[String]): Unit = {
    //创建
    val lis01 = new ListBuffer[Any] //创建一个空list
    val lis02 = ListBuffer[Any]("Lucy","sunny",3.14)
    val lis03 = ListBuffer("Lucy","sunny",3.14)

    println(lis01) //ListBuffer()
    println(lis02) //ListBuffer(Lucy, sunny, 3.14)
    println(lis03) //ListBuffer(Lucy, sunny, 3.14)

    //添加元素 +=、append、++=不会生成一个新得集合
    val lis04 = new ListBuffer[Any]() //可省略()
    lis04 += ("@Lucy","@sunny")
    lis04.append("A","B",18)
    println(lis04) //ListBuffer(@Lucy, @sunny, A, B, 18)

    val lis05 = ListBuffer(3.14,6.28)
    lis04 ++= lis05
    println(lis04) //ListBuffer(@Lucy, @sunny, A, B, 18, 3.14, 6.28)

    // ++、:+、+: 会生成一个新的集合
    val lis06 = ListBuffer("Lucy","@Lucy")
    val lis07 = ListBuffer("加菲猫","中华田园犬")
    val lis08 = lis06 ++ lis07
    val lis09 = lis08 :+ "1998"
    val lis10 = "1998" +: lis08
    println(lis06) //ListBuffer(Lucy, @Lucy)
    println(lis07) //ListBuffer(加菲猫, 中华田园犬)
    println(lis08) //ListBuffer(Lucy, @Lucy, 加菲猫, 中华田园犬)
    println(lis09) //ListBuffer(Lucy, @Lucy, 加菲猫, 中华田园犬, 1998)
    println(lis10) //ListBuffer(1998, Lucy, @Lucy, 加菲猫, 中华田园犬)

    //删除元素
    val elem = lis10.remove(0) //可以不用变量接收
    println(s"删除的元素:$elem") //删除的元素:1998
    println(lis10)  //ListBuffer(Lucy, @Lucy, 加菲猫, 中华田园犬)

  }
}

5.队列Queue

1)创建队列
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2)添加、删除元素
在这里插入图片描述
3)返回队列元素
在这里插入图片描述

package scalaDemo.collectionDemo.queue

import scala.collection.mutable.Queue

object QueueV1 {
  def main(args: Array[String]): Unit = {
    //创建
    val que01 = new Queue[Any]

    //添加元素
    que01 += "Lucy"
    que01 ++= List(1,2,3)
    println(que01) //Queue(Lucy, 1, 2, 3)

    que01 += List('A','B','C')
    println(que01) //Queue(Lucy, 1, 2, 3, List(A, B, C))

    //从队列的头部取出元素,队列que01本身也会变
    val elem = que01.dequeue()
    println(s"elem==$elem") //elem==Lucy
    println(que01) //Queue(1, 2, 3, List(A, B, C))

    //默认从尾部入队列,队列que01本身也会变
    que01.enqueue(3.14,6.28,9.32)
    println(que01) //Queue(1, 2, 3, List(A, B, C), 3.14, 6.28, 9.32)

    //返回队列元素,队列que02本身不变
    val que02 = new Queue[Any]
    que02 ++= List('A','B','C','D')
    //获取队列的第一个元素
    println(s"head:${que02.head}") //head:A
    //获取队列的最后一个元素
    println(s"last:${que02.last}") //last:D
    //获取队尾元素,即返回除了第一个以外剩余的元素
    println(s"tail:${que02.tail}") //tail:Queue(B, C, D)
    println(s"tail:${que02.tail.tail}") //tail:Queue(C, D)
  }
}

6.映射Map

6.1 不可变Map

在这里插入图片描述
在这里插入图片描述

    /**
      * @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)
      *         def →[B](y: B): Tuple2[A, B] = ->(y)
      **/
    //创建不可变Map--输出顺序和声明顺序一致
    val map01 = Map("鞠婧祎" -> 25, "刘亦菲" -> 31)
    val map02 = Map(("Lucy", 25), ("sunny", 31))

6.2 可变Map

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo.collectionDemo.map

import scala.collection.mutable.Map
import scala.collection.mutable.HashMap

object MapV2 {
  def main(args: Array[String]): Unit = {
    //创建可变Map
    val map01 = Map("杨幂" -> "三生三世十里桃花", "胡歌" -> "琅琊榜")
    val map02 = Map(("Lucy", 25), ("sunny", 31))

    //空集合--Map()
    val map03 = new HashMap[String, Int]

    //取值
    //方式1:map(key)
    println(map02("Lucy")) //key不存在会抛异常

    //方式2:contains(key)先判断key是否存在
    if (map02.contains("@sunny")) {
      map02("@sunny")
    }

    //方式3:get(key)
    val some01 = map02.get("Lucy")
    val some02 = map02.get("@Lucy")
    println(some01) //Some(25)
    println(some02) //None
    println(some01.get) //25
    //println(some02.get) //None类型不能再get

    //方式4:getOrElse(key,默认值)
    val value01 = map02.getOrElse("Lucy~~", "-1")
    println(value01) //-1

    //修改和添加
    val map04 = Map("杨幂" -> "三生三世十里桃花", "胡歌" -> "琅琊榜")
    map04("胡歌") = "仙剑奇侠传" //key存在,更新value值
    map04("鞠婧祎") = "叹云夕" //key不存在,相当于添加一个key-value
    map04.update("杨幂", "古剑奇谭") //update更新value值
    println(map04) //Map(鞠婧祎 -> 叹云夕, 胡歌 -> 仙剑奇侠传, 杨幂 -> 古剑奇谭)
    // += 也能添加元素,如果key存在,则更新
    map04 += "赵露思" -> "女"
    map04 += ("杨紫" -> "女", "任嘉伦" -> "男")
    map04 += (("Lucy", "女"), ("@Lucy", "女"))
    println(map04) //Map(任嘉伦 -> 男, 鞠婧祎 -> 叹云夕, 胡歌 -> 仙剑奇侠传, 赵露思 -> 女, 杨紫 -> 女, 杨幂 -> 古剑奇谭, @Lucy -> 女, Lucy -> 女)

    //删除--如果key不存在,也不会报错
    map04 -= ("Lucy", "@Lucy")
    println(map04) //Map(任嘉伦 -> 男, 鞠婧祎 -> 叹云夕, 胡歌 -> 仙剑奇侠传, 赵露思 -> 女, 杨紫 -> 女, 杨幂 -> 古剑奇谭)

    //遍历
    for ((k,v) <- map04) println(s"key==$k value==$v")

    for (k <- map04.keys) println(s"key==$k")

    for (v <- map04.values) println(s"value==$v")

    for (tuple <- map04) println(s"key==${tuple._1} value==${tuple._2}")
  }
}

7.Set

7.1 不可变Set

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

7.2 可变Set

package scalaDemo.collectionDemo.set

import scala.collection.mutable
import scala.collection.mutable.HashSet

object SetV1 {
  def main(args: Array[String]): Unit = {
    //创建
    val set01 = mutable.Set.empty[Any]
    val set02 = mutable.Set("Lucy",1,2,3)
    val set03 = new HashSet[String] ()
    val set04 =  mutable.HashSet.empty[Any]

    //添加元素
    set01 += ("@Lucy","sunny",2008,2018)
    set04.add("@Lucy")
    println(set01) //Set(@Lucy, sunny,2008,2018)

    //删除元素
    set01 -= "sunny"
    set01.remove(2008)
    println(set01) //Set(@Lucy,2018)

    //遍历
    for (elem <- set01) println(elem)
    set01.foreach {elem => println(elem)}
  }
}

六、模式匹配

在这里插入图片描述
在这里插入图片描述

  def matchCase(element: Any) = {
    element match {
      case a: Char => s"char类型$a"
      case a: Int => s"int类型$a"
      case a: Long => s"Long类型$a"
      case a: Float => s"float类型$a"
      case a: Double => s"double类型$a"
      case a: Boolean => s"布尔类型$a"
      case b: String => s"string类型$b"
      case _ => s"未匹配到..."
    }
  }

在这里插入图片描述

七、函数

1.偏函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo.partialFunDemo

object PartialFunctionV1 {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3,3.14, "Lucy")
    val res01 = list.filter(_.isInstanceOf[Int]).map(func01(_))
    val res02 = list.map(func02(_)).filter(_.isInstanceOf[Int])
    println(res01)
    println(res02)

    //偏函数 可以处理多种类型
    val func04 = new PartialFunction[Any, Int] {
      override def isDefinedAt(x: Any): Boolean = x.isInstanceOf[Int] || x.isInstanceOf[Double]

      override def apply(v1: Any): Int = if(v1.isInstanceOf[Int]) v1.asInstanceOf[Int]*2 else v1.asInstanceOf[Double].toInt +10
    }

    //偏函数简化形式
    def func05: PartialFunction[Any, Int] = {
      case x: Int => x * 2 //这里case语句可以自动转化成偏函数
      case x: Double => x.toInt + 10
    }

    //如果使用偏函数,则不能使用map算子,应该使用collect(相当于map+filter组合使用)
    val res04 = list.collect(func04)
    val res05 = list.collect(func05)
    println(res04)
    println(res05)
  }

  def func01(x: Any): Int = {
    x.asInstanceOf[Int] * 2
  }

  //模式匹配
  def func02(x: Any) = {
    x match {
      case num: Int => num * 2
      case _ =>
    }
  }

  //偏函数
  def func03 = {
    val value = new PartialFunction[Any, Int] {
      override def isDefinedAt(x: Any): Boolean = x.isInstanceOf[Int]

      override def apply(v1: Any): Int = v1.asInstanceOf[Int] * 2
    }
    value
  }
}

2.匿名函数

在这里插入图片描述

3.高阶函数

在这里插入图片描述

package scalaDemo.higherFunDemo

object HigherFunctionV1 {
  def main(args: Array[String]): Unit = {
    val res01 = hFuncA(funcA,3.14)
    val res02 = hFuncA(funcB,6.28)
    val res03 = hFuncA(funcC,9.42)
    val res04 = hFuncB(funcC,funcD,9.42)
    println(res01)
    println(res02)
    println(res03)
    println(res04)
  }

  val funcA: Double => Int = num => num.toInt*2

  def funcB = (num: Double) => num.toInt*2

  def funcC(num: Double): Int = {
    num.toInt*2
  }

  def funcD(num: Double) = {
    num*num
  }

  def hFuncA(f: Double => Int, num: Double): Int = {
    f(num)
  }

  def hFuncB(f1: Double => Int, f2: Double => Double, num: Double): Int = {
    f1(f2(num))
  }
}

在这里插入图片描述

package scalaDemo.higherFunDemo

object HigherFunctionV2 {
  def main(args: Array[String]): Unit = {
    val res01 = hFuncA(3)(3.14)
    println(res01)

    val func01 = hFuncA(4) // func01为3*y
    val res02 = func01(3.14)
    println(func01)  //<function1>
    println(res02)
  }

  //高阶函数也可以返回一个函数
  def hFuncA(x: Int) = {
    y: Double => x * y //匿名函数
  }
}

在这里插入图片描述
在这里插入图片描述

package scalaDemo.higherFunDemo

object HigherFunctionV3 {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4,5)
    val res01 = list.map((x: Int) => x + 10) //map是一个高阶函数,可以直接传入匿名函数
    val res02 = list.map((x) => x + 10) //由于list全是Int类型,在这里可推导出具体类型,所有可省略具体类型
    val res03 = list.map(x => x + 10) //参数只有一个,可省略()
    val res04 = list.map(_ + 10) //由于参数x在 => 右边只出现1次,可用_代替
    println(res04)

    val lis01 = list.reduce((x: Int,y: Int) => x + y)
    val lis02 = list.reduce((x,y) => x + y)
    val lis03 = list.reduce(_+_) //x和y在 => 右边只出现1次,可用_代替
    println(lis03)
  }
}

4.闭包

在这里插入图片描述
在这里插入图片描述

package scalaDemo.higherFunDemo

object HigherFunctionV4 {
  def main(args: Array[String]): Unit = {
    val res01 = hFuncA(funcA,"Lucy.jpg",".jpg")
    val res02 = hFuncA(funcA,"sunny",".jpg")
    println(res01)
    println(res02)

    println(hFuncB(".jpg")("@sunny"))

    //闭包可以保留上次引用的某个值,传入一次可以反复使用
    val endFunc = hFuncB(".jpg")
    val list = List("Lucy.jpg","sunny","@sunny")
    val res04 = list.map(endFunc) //.jpg传入一次,map遍历时多次使用
    println(res04)

  }

  def funcA(file: String, end: String): String = {
    if(file.endsWith(end)) {
      file
    } else
      file + end
  }

  def hFuncA(f: (String, String) => String, file: String, end: String): String = {
    funcA(file,end)
  }

  //这里匿名函数和end参数形成一个闭包
  def hFuncB(end: String) = {
    file: String => {
      if(file.endsWith(end))
        file
      else
        file + end
    }
  }
}

在这里插入图片描述

5.柯里化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package scalaDemo.higherFunDemo

object HigherFunctionV5 {
  def main(args: Array[String]): Unit = {
    val str1 = "Lucy"
    val str2 = "@Lucy"
    val res01 = str1.checkEq(str2)(eq)
    println(res01)
  }

  /**
    *函数柯里化:
    * 将比较字符串分成两个任务完成:
    * 1.checkEq 完成转化大小写
    * 2.函数f 完成比较任务
    *
   **/
  implicit class TestEq(s: String) {
    def checkEq(ss: String)( f: (String, String) => Boolean) = {
      f(s.toLowerCase,ss.toLowerCase)
    }
  }

  def eq(s1: String, s2: String): Boolean = {
    s1.equals(s2)
  }
}

八、泛型

1.1 上边界

package scalaDemo.boundType

object BoundTypeV4 {
  def main(args: Array[String]): Unit = {

    /**
      * 调用了Predef中的隐式函数:
      * implicit def int2Integer(x: Int)          = java.lang.Integer.valueOf(x)
      * implicit def double2Double(x: Double)     = java.lang.Double.valueOf(x)
      * 指定泛型后,入参中的Int和Double类型通过隐式转换成了实现Comparable接口的java中的Integer和Double类型
      **/
    val com01 = new Compare[Integer](Integer.valueOf(2), 5)
    val com02 = new Compare[java.lang.Double](6.6, 9.9)
    println(com01.myCompare)
    println(com02.myCompare)
  }
}

/**
  * 上边界:A <: B 表示A为B类型或B类型的子类
  * T <: Comparable[T] 这里表示T类型是实现了Comparable接口的一个类型
  * 这样传入的参数类型可以直接调用compareTo方法
  **/

class Compare[T <: Comparable[T]](one: T, other: T) {
  private val i: Int = one.compareTo(other)

  def myCompare = if (i > 0) one else other
}

1.2 下边界

package scalaDemo.boundType

object BoundTypeV5 {
  def main(args: Array[String]): Unit = {
    val list01 = List(new ElecGoodsA, new PhoneA)
    val list02 = List(new PhoneA, new HuaWeiPhoneA)
    //info01(list01) //报错 ElecGoodsA不是PhoneA类及其子类
    info01(list02)

    println("***************")


    /**
      * 下边界:A >: B  下界比较特殊,这里A类型其实可以传入任意类型
      *  传入和B有直系关系的,如果是B的父类还是按照父类处理,如果是B子类的按照B类型处理,
      *  传入和B没有继承和被继承关系的,一律按照Object处理
      **/
    val list03 = List(new ElecGoodsA, new PhoneA, new HuaWeiPhoneA)
    info02(list03).foreach(_.getInfo)

    //这里ElecGoodsB和PhoneA没有直系关系,调用info02方法后:
    //List[Object] = List(ElecGoodsB@3fb6a447),所以asInstanceOf转换类型后才能访问getInfo方法
    val list04 = List(new ElecGoodsB)
    info02(list04).map(obj => obj.asInstanceOf[ElecGoodsB].getInfo)
    info02(list04).map(obj => println(obj.toString)) //scalaDemo.boundType.ElecGoodsB@3fb6a447

  }

  //上边界  A <: B 表示A为B类型或B类型的子类
  def info01[T <: PhoneA](list: List[T]) = list.foreach(_.getInfo)

  //下边界  A >: B  下界比较特殊,这里可以传入任意类型
  def info02[T >: PhoneA](list: List[T]) = list
}

class ElecGoodsB {
  private val message: String = "电子产品B"

  def getInfo = println(message)
}

class ElecGoodsA {
  private val message: String = "电子产品A"

  def getInfo = println(message)
}

class PhoneA extends ElecGoodsA {
  private val message: String = "手机"

  override def getInfo: Unit = println(message)
}

class HuaWeiPhoneA extends PhoneA {
  private val message: String = "华为手机"

  override def getInfo: Unit = println(message)
}

1.3 协变和逆变

在这里插入图片描述
在这里插入图片描述

package scalaDemo.boundType

object BoundTypeV7 {
  def main(args: Array[String]): Unit = {
    val child = new Child08A
    val father = new Father08A
    child.info //Father...

    //编译阶段报错:Top08A[Father08A]和Top08A[Child08A]没有继承关系
    //val top01: Top08A[Father08A] = new Top08A[Child08A](child)

    //协变
    val top02: Top08B[Father08A] = new Top08B[Child08A](child)

    //逆变
    val top03: Top08C[Child08A] = new Top08C[Father08A](father)
    
  }
}

class Father08A {
  private val message = "Father..."
  val job = "work..."

  def info = println(message)
}

class Child08A extends Father08A {
  private val message = "Child..."
  override val job: String = "study..."
}

//不变
class Top08A[A](one: A) {
  def getClassInfo = {
    one.getClass.getName
  }
}

//协变
class Top08B[+A](one: A) {
  def getClassInfo = {
    one.getClass.getName
  }
}

class Top08C[-A](one: A) {
  def getClassInfo = {
    one.getClass.getName
  }
}

1.4 上下文界定

在这里插入图片描述
在这里插入图片描述

1.5 视图界定

九、递归

package scalaDemo

object Fibnacci {
  def main(args: Array[String]): Unit = {
    println(fibn(7))
  }

  /**
   * @Author: qwerdf@QAQ
   * @Description: 斐波那契数列数列从第3项开始,每一项都等于前两项之和
    * 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597 ...
    * 示例: n=7 输出13
    * 第1次入栈:main栈  println(fibn(7))    最后输出:13
    * 第2次    fibn1栈  fibn(7)    fibn(n - 2) + fibn(n - 1)  返回9:5 + 8 = 13
    * 第3次    fibn(n - 2)  = fibn(5)    返回值8: 5
    *          fibn(n - 1) = fibn(6)    返回值7: 8
    * 第4次    fibn(5 - 2) + fibn(5 - 1) = fibn(3) + fibn(4)  返回值6:2+3=5
    *          fibn(6 - 2) + fibn(6 - 1) = fibn(4) + fibn(5) 返回值5:3+5=8
    * 第5次    f(1) + f(2) = 2
    *          f(2) + f(3) = 1 + f(3)   返回值4:1+2=3
    *          f(2) + f(3) = 1 + f(3)   返回值3:1+2=3
    *          f(3) + f(4)    返回值1:2+3=5
    *第6次     f(1) + f(2) = 2
    *          f(1) + f(2) = 2
    *          f(1) + f(2) = 2
    *          f(2) + f(3) = 1 + f(3)   返回值1:1+2=3
    *第7次     f(1) + f(2) = 2
    *
    *备注:先入栈则后出栈
    *
   * @Date: 2022/4/23
   * @Param null:
   * @return: null
   **/
 //递归函数编译阶段无法推断具体的结果类型,必须指定返回值类型
  val fibn: Int => Int = n => {
      if (n == 1 || n == 2) {
        1
      } else {
        fibn(n - 2) + fibn(n - 1)
      }
  }
}

十、常用操作

1.跳出循环

package scalaDemo

import util.control.Breaks._

object CircleBreak {
  def main(args: Array[String]): Unit = {

    //方式1:通过调用break函数实现中断
    var num1 = 0
    breakable {
      while (num1 <= 50) {
        if (num1 % 2 != 0) {
          println(s"num1==$num1")
        }

        if (num1 == 9) {
          println("while循环中断...\r\nfor循环开始...")
          break()
        }
        num1 += 1
      }
    }

    breakable {
      for (num2 <- 1 to 50) {
        if (num2 % 2 == 0) {
          println(s"num2==$num2")
        }
        if (num2 == 10) {
          println("for循环中断...\r\n")
          break()
        }
      }
    }

    //方式2:通过循环守卫实现中断
    var flag = true
    //def apply(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
    for (num3 <- Range(1, 10, 2) if flag) {
      if (num3 == 5) {
        flag = false
        println("结束循环...")
      } else {
        println(s"num3==$num3")
      }
    }

    //方式3:通过引入外部变量
    val arr = Array('a','b','c','d','e','f')
    var i = 0
    var elem = ' '
    var tmpf = true
    while ({elem = arr(i); i <= arr.length && tmpf}) {
      if (elem != 'd') {
        println(elem)
      } else {
        println("结束循环...")
        tmpf = false
      }

      i +=1
    }

  }
}

2.实现continue效果

package scalaDemo

object CircleContinue {
  def main(args: Array[String]): Unit = {
    //方式1:通过循环守卫实现continue效果
    for (i <- 1 to 10 if i % 2 == 0) {
      println(s"i==$i")
    }

    var j = 0
    while (j <= 10) {
      //方式2:通过if表达式实现continue效果
      if (j % 2 != 0) {
        println(s"j==$j")
      }
      j +=1
    }
  }
}

3.for过滤器

//for过滤器函数
val grepFunc = (books: ArrayBuffer[String], grepPattern: String) => {
  if (books != null) {
    val greps: ArrayBuffer[String] = for {
      book <- books
      if (book.contains(grepPattern))
    } yield book
    println(greps)
  }
}

//for过滤器方法
def grep(books: ArrayBuffer[String]): ArrayBuffer[String] = {
  var greps: ArrayBuffer[String] = null
  if (books != null) {
    greps = for {
      book <- books
      if (book.length == 3)
    } yield book
  }
  greps
}

4.异常处理

package scalaDemo
import com.sun.xml.internal.bind.v2.TODO

object TryCatch {
  def main(args: Array[String]): Unit = {

    /**
      * @Author: qwerdf@QAQ
      * @Description: 将可能发生异常的代码封装在try块中,catch块用来捕获异常并处理,避免程序异常中止
      *              1.在scala中只有一个catch,在java中可以有多个
      *              2.在catch中有多个case,每个case匹配一种异常,即模式匹配思想。
      * @Date: 2022/4/24
      * @Param args:
      * @return: void
      **/
    try {
      val num = 9 / 0
    } catch {
      case ex: ArithmeticException => {
        //TODO  捕获异常,处理业务逻辑
        println("捕获了除数为零的算术异常")
      }
      case ex: Exception => {
        //TODO  捕获异常,处理业务逻辑
        println("捕获了异常")
      }
    } finally {
      //TODO 有无异常都会执行的代码块,一般用于关闭数据库连接、IO流等
      println("执行finally代码块...")
    }

    println("程序继续执行...")
  }
}

变长参数

//变长参数
def method1(author: String, books: String*): String = {
  val buffer = new StringBuffer()
  var res: String = ""
  if (!author.isEmpty && books != null) {
    buffer.append(author + ":")
    for (book <- books) {
      buffer.append(book + "|")
    }
    val tmpStr = buffer.toString
    res = tmpStr.substring(0,tmpStr.length-1)
  }
  res
}
//测试
val res1 = method1("古龙","武林外史","绝代双骄","楚留香传奇","多情剑客无情剑","萧十一郎","流星蝴蝶剑","边城浪子")
println(res1)

总结

未完待续…
待补充:
1.数据结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值