scala

 面向对象

Scala 的面向对象思想和Java 的面向对象思想和概念是一致的。

Scala 中语法和 Java 不同,补充了更多的功能。

6.1类和对象详解

6.1.1组成结构

  • 构造函数: 在创建对象的时候给属性赋值
  • 成员变量:
  • 成员方法(函数)
  • 局部变量
  • 代码块

6.1.2构造器

每个类都有一个主构造器,这个构造器和类定义"交织"在一起类名后面的内容就是主构造器,如果参数列表为空的话,()可以省略
scala的类有且仅有一个主构造器,要想提供更加丰富的构造器,就需要使用辅助构造器,辅助构造器是可选的,它们叫做this   def this

注意:主构造器会执行类定义中的所有语句

代码示例:

Scala
// 类默认有一个无参的主构造函数
class User {
}

val user: User = new User

//
两个参数的主构造函数
class User2(val name: String, age: Int) {

}
val user2 = new User2("jim", 23)
//
使用val修饰的变量默认是成员变量,对象可以访问
// user2.age   // age没有使用val或者var修饰 所以不能被访问,他不是一个成员变量,而是一个局部变量


//辅助构造器
class User3 {
   var name: String = _
   var age: Int = _
  // 辅助构造函数
  def this(name: String, age: Int) {
    // 构造函数中的首行必须调用主构造函数或者其他构造函数
    this()
    this.name = name
    this.age = age
  }
  // 辅助构造函数
  def this(msg: String) = {
    // 首行调用一个构造
    this("ww", 12)
    println(msg)
  }
}
val u1 = new User3()
val u2 = new User3("")
val u3 = new User3("lisi", 23)
println(u3.name)

总结:

  1. 有两类构造器:主构造器,辅助构造器
  1. 构造器的定义位置:主构造器和类交织在一起,class Student2(val name: String, var age: Int)
  1. 辅助构造器是一个特殊的方法,定义在类中 def this(name:String,age:Int,gender:String)
  1. 辅助构造器,第一行必须调用主构造器(或者其他的辅助构造器)
  1. 辅助构造器的参数不能和主构造器的参数完全一致(参数个数,参数类型,参数顺序)
  1. 可以定义空参的辅助构造器,但是主构造器的参数必须进行初始化赋值
  1. 作用域:辅助构造器的变量作用域,只在方法中,主构造器的作用域是类中除了成员属性和成员方法之外的所有范围(可以通过反编译查看源码)

构造器的参数说明

  • 主构造函数中使用val 和 var修饰的变量为成员变量
  • val 修饰的变量默认只有getter方法   一要初始化
  • var 修饰的变量默认有 get和set方法  直接点属性操作  使用 _ 占位可以稍后赋值
  • @BeanProperty会生成getMsg setMsg方法

6.1.3成员方法/函数

在类的成员位置定义的函数或者方法是类的成员的一部分

6.1.4代码块

在类或者对象中的代码块在实例化的时候会被调用 

  • 在类成员位置的代码块  构造代码块 每次创建对象都会执行一次
  • 在object中成员位置的代码块是静态代码块  只执行一次
  • 代码有返回值

6.1.5object类的底层原理

Scala
package com.doit.day01.day02

//如果构造器中的变量,不加var 或者val 那他就是一个局部变量
//加了var 或者val 的话他就是一个私有的成员变量
class Student1(var id: Int, val name: String) {

  def sayHello: Unit = {
    println(name + ":
你好")
  }

  val sayFunc = () => {
    println("hello:" + name)
  }
}


object Student2{
  var id: Int = 1
  //
如果在成员变量的位置上给一个_作为占位符,相当于是给他赋了一个默认值啊
  var name: String =_

  def sayHello: Unit = {
    println(name + ":
你好")
  }
  val sayFunc = (x:String) => {
    println("hello:" + name + x)
  }
}


object Demo01_
面向对象 {
  def main(args: Array[String]): Unit = {

    Student2.sayFunc("a")

    val student1: Student1 = new Student1(1, "zhangsan")
    println(student1.name)
    println(student1.id)
    //    student1.name = "lisi" 
用val 修饰的,不能修改
    student1.id = 2
    println(student1.id)

    student1.sayHello
    student1.sayFunc()
    println(Student2.name)
  }
}

java手写实现:

Java
package com.doit;


public class Person {
    public static String getName(){
        return Person$.person.getName();
    }

    public static Integer getAge(){
        return Person$.person.getAge();
    }

    public static void setName(String name ){
        Person$.person.setName(name);
    }

    public static void setAge(Integer age ){
        Person$.person.setAge(age);
    }
}

class Person$ {
    //
自己的对象
    public static Person$ person ;
    //
成员变量
    private String name;
    private int age;

    static {
        person  = new Person$();
    }

    private Person$() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


class Test{
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("张三");
        person.setAge(18);
        String name1 = person.getName();
        Integer age1 = person.getAge();
        System.out.println(name1);
        System.out.println(age1);
    }
}

scala中底层反编译后的代码:

Java
//decompiled from Student2$.class
package com.doit.day01.day02;

import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef.;
import scala.runtime.BoxedUnit;

public final class Student2$ {
   public static Student2$ MODULE$;
   private int id;
   private String name;
   private final Function1 sayFunc;

   static {
      new Student2$();
   }

   public int id() {
      return this.id;
   }

   public void id_$eq(final int x$1) {
      this.id = x$1;
   }

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

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

   public void sayHello() {
      .MODULE$.println((new StringBuilder(3)).append(this.name()).append(":
你好").toString());
   }

   public Function1 sayFunc() {
      return this.sayFunc;
   }

// $FF: synthetic method
   public static final void $anonfun$sayFunc$1(final String x) {
      .MODULE$.println((new StringBuilder(6)).append("hello:").append(MODULE$.name()).append(x).toString());
   }

   private Student2$() {
      MODULE$ = this;
      this.id = 1;
      this.sayFunc = (x) -> {
         $anonfun$sayFunc$1(x);
         return BoxedUnit.UNIT;
      };
   }

// $FF: synthetic method
   private static Object $deserializeLambda$(SerializedLambda var0) {
      return var0.lambdaDeserialize<invokedynamic>(var0);
   }
}

 //decompiled from Student2.class
package com.doit.day01.day02;

import scala.Function1;
import scala.reflect.ScalaSignature;

@ScalaSignature(
   bytes = "\u0006\u0001!;Q\u0001D\u0007\t\u0002Y1Q\u0001G\u0007\t\u0002eAQ\u0001I\u0001\u0005\u0002\u0005BqAI\u0001A\u0002\u0013\u00051\u0005C\u0004(\u0003\u0001\u0007I\u0011\u0001\u0015\t\r9\n\u0001\u0015)\u0003%\u0011%y\u0013\u00011AA\u0002\u0013\u0005\u0001\u0007C\u0005=\u0003\u0001\u0007\t\u0019!C\u0001{!Iq(\u0001a\u0001\u0002\u0003\u0006K!\r\u0005\u0006\u0001\u0006!\t!\u0011\u0005\b\u0005\u0006\u0011\r\u0011\"\u0001D\u0011\u00199\u0015\u0001)A\u0005\t\u0006A1\u000b^;eK:$(G\u0003\u0002\u000f\u001f\u0005)A-Y=1e)\u0011\u0001#E\u0001\u0006I\u0006L\b'\r\u0006\u0003%M\tA\u0001Z8ji*\tA#A\u0002d_6\u001c\u0001\u0001\u0005\u0002\u0018\u00035\tQB\u0001\u0005TiV$WM\u001c;3'\t\t!\u0004\u0005\u0002\u001c=5\tADC\u0001\u001e\u0003\u0015\u00198-\u00197b\u0013\tyBD\u0001\u0004B]f\u0014VMZ\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0003Y\t!!\u001b3\u0016\u0003\u0011\u0002\"aG\u0013\n\u0005\u0019b\"aA%oi\u00061\u0011\u000eZ0%KF$\"!\u000b\u0017\u0011\u0005mQ\u0013BA\u0016\u001d\u0005\u0011)f.\u001b;\t\u000f5\"\u0011\u0011!a\u0001I\u0005\u0019\u0001\u0010J\u0019\u0002\u0007%$\u0007%\u0001\u0003oC6,W#A\u0019\u0011\u0005IJdBA\u001a8!\t!D$D\u00016\u0015\t1T#\u0001\u0004=e>|GOP\u0005\u0003qq\ta\u0001\u0015:fI\u00164\u0017B\u0001\u001e<\u0005\u0019\u0019FO]5oO*\u0011\u0001\bH\u0001\t]\u0006lWm\u0018\u0013fcR\u0011\u0011F\u0010\u0005\b[\u001d\t\t\u00111\u00012\u0003\u0015q\u0017-\\3!\u0003!\u0019\u0018-\u001f%fY2|W#A\u0015\u0002\u000fM\f\u0017PR;oGV\tA\t\u0005\u0003\u001c\u000bFJ\u0013B\u0001$\u001d\u0005%1UO\\2uS>t\u0017'\u0001\u0005tCf4UO\\2!\u0001"
)
public final class Student2 {
   public static Function1 sayFunc() {
      return Student2$.MODULE$.sayFunc();
   }

   public static void sayHello() {
      Student2$.MODULE$.sayHello();
   }

   public static void name_$eq(final String x$1) {
      Student2$.MODULE$.name_$eq(var0);
   }

   public static String name() {
      return Student2$.MODULE$.name();
   }

   public static void id_$eq(final int x$1) {
      Student2$.MODULE$.id_$eq(var0);
   }

   public static int id() {
      return Student2$.MODULE$.id();
   }
}

练一练

需求1:1.定义一个object,里面放一个成员:base = 100

     2.定义一个工具方法:求两数之和,如果和<base 返回和,否则返回base

     3.定义一个工具函数:求两数的差,并且返回(差值<base 就返回base,否则返回差值)

     4.定义一个工具函数:求三个数的最大值,如果最大值<base 就返回base,否则返回最大值

Scala
object Max {
  val base = 100

  def sum(i: Int, j: Int) = {
    if (i + j < base) base else i + j
  }

  val cha = (i: Int, j: Int) => {
   
c
  }

  val max = (a: Int, b: Int, c: Int) => {
    var mx = a
    if (b > mx) mx = b
    if (c > mx) mx = c
    if (mx > base) mx else base
  }
}

需求2:用java模拟一个object内部的实现原理,把需求1这个object类模拟出来

Java
//函数对应的接口
package com.doit;

public interface Function3<U,V,Y,Z> {
    Z apply(U u,V v,Y y);
}



package com.doit;

public interface Function2<U,V,T> {
    T apply(U u,V v);
}


//对象的.class
package com.doit;

//都是放的静态的
class Max {
    //这里面都是静态的,用Max$里面定义的对象去调用所有的成员属性,方法和函数
    private static int getBase(){
        return Max$.MODULE$.getBase();
    }

    private static int getMax(int a,int b,int c){
        return Max$.MODULE$.getMax().apply(a,b,c);
    }

    private static int getCha(int a,int b){
        return Max$.MODULE$.getCha().apply(a,b);
    }

    private static int getSum(int a,int b){
        return Max$.MODULE$.getCha().apply(a,b);
    }

}

//类似于java中的.class
class Max$ {
    //还要定义一个自己的对象,对象名字是MODULE$,为了上面静态的能访问到,所以他也要是静态的
    public static Max$ MODULE$;
    //定义成员变量,val修饰的,在java中前面要加final修饰
    private final Integer base = 100;
    //定义两个函数
    //两个数求差的函数
    private final Function2<Integer, Integer, Integer> cha = new Function2<Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer integer, Integer integer2) {
            return integer + integer2;
        }
    };

    //三个数求最大值的函数
    private final Function3<Integer, Integer, Integer, Integer> max = new Function3<Integer, Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer a, Integer b, Integer c) {
            int mx = a;
            if (b > mx) mx = b;
            if (c > mx) mx = c;
            if (mx < base) mx = base;
            return mx;
        }
    };

    //定义方法,两数求和
    public int sum(int a ,int b ){
        return a+b;
    }

    //get和set方法
    public int getBase(){
        return base;
    }
    //base 是常量,所以这边不用写set方法
//    private void setBase(int num){
//        this.base = num;
//    }

    //函数本质上也是一个类型哦,所以他也是成员变量的地位,需要写get方法哦

    public Function2<Integer, Integer, Integer> getCha(){
        return this.cha;
    }

    public Function3<Integer, Integer, Integer,Integer> getMax(){
        return this.max;
    }

    static {
        new Max$();
    }

    private Max$() {
        MODULE$ = this;
    }


}

6.1.6伴生类和伴生对象

条件 1:在同一个源文件中, 条件 2:对象名和类名相同

Scala
  //类名和object的名称一致
  //类是对象的伴生类
  //对象是类的伴生对象

class Demo6(val name: String) {
}
object Demo6 {
}

条件 2:伴生对象和伴生类之间可以互相访问彼此的私有属性和私有方法

Scala
package com.doit.day01.day02

/**
 *
伴生对象的用途:
 *      1.可以将静态的成员变量和普通成员变量分别声明
 *      2.伴生对象自己内部定义了一个apply方法,可以简化创建对象(类的实例构造)
 *      3.伴生对象自己定义了一个unapply方法,可以用于模式匹配
 */
class Car(var brand: String, var price: Double) {

  def sayHello(): Unit ={
    println("hello")
  }

  private val color: String = Car.color
  Car.start()
}


object Car {
  var color :String = "red"

  def start(): Unit ={
    println("汽车启动了,嗡~~~~~~~~")
  }
}

object Demo02_伴生对象 {
  def main(args: Array[String]): Unit = {
    val car: Car = new Car("华为", 9.9)
    println(car.brand)
    println(car.price)
    car.sayHello()
    Car.start()
  }
}

伴生对象的底层原理:

Java
//decompiled from Car.class
package com.doit.day01.day02;

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

@ScalaSignature(
   bytes = "\u0006\u0001E3A\u0001E\t\u00015!A\u0011\u0005\u0001BA\u0002\u0013\u0005!\u0005\u0003\u0005/\u0001\t\u0005\r\u0011\"\u00010\u0011!)\u0004A!A!B\u0013\u0019\u0003\u0002\u0003\u001c\u0001\u0005\u0003\u0007I\u0011A\u001c\t\u0011m\u0002!\u00111A\u0005\u0002qB\u0001B\u0010\u0001\u0003\u0002\u0003\u0006K\u0001\u000f\u0005\u0006\u007f\u0001!\t\u0001\u0011\u0005\u0006\u000b\u0002!\tAR\u0004\u0006\u000fFA\t\u0001\u0013\u0004\u0006!EA\t!\u0013\u0005\u0006\u007f)!\tA\u0013\u0005\b\u0017*\u0001\r\u0011\"\u0001#\u0011\u001da%\u00021A\u0005\u00025Caa\u0014\u0006!B\u0013\u0019\u0003\"\u0002)\u000b\t\u00031%aA\"be*\u0011!cE\u0001\u0006I\u0006L\bG\r\u0006\u0003)U\tQ\u0001Z1zaER!AF\f\u0002\t\u0011|\u0017\u000e\u001e\u0006\u00021\u0005\u00191m\\7\u0004\u0001M\u0011\u0001a\u0007\t\u00039}i\u0011!\b\u0006\u0002=\u0005)1oY1mC&\u0011\u0001%\b\u0002\u0007\u0003:L(+\u001a4\u0002\u000b\t\u0014\u0018M\u001c3\u0016\u0003\r\u0002\"\u0001J\u0016\u000f\u0005\u0015J\u0003C\u0001\u0014\u001e\u001b\u00059#B\u0001\u0015\u001a\u0003\u0019a$o\\8u}%\u0011!&H\u0001\u0007!J,G-\u001a4\n\u00051j#AB*ue&twM\u0003\u0002+;\u0005I!M]1oI~#S-\u001d\u000b\u0003aM\u0002\"\u0001H\u0019\n\u0005Ij\"\u0001B+oSRDq\u0001\u000e\u0002\u0002\u0002\u0003\u00071%A\u0002yIE\naA\u0019:b]\u0012\u0004\u0013!\u00029sS\u000e,W#\u0001\u001d\u0011\u0005qI\u0014B\u0001\u001e\u001e\u0005\u0019!u.\u001e2mK\u0006I\u0001O]5dK~#S-\u001d\u000b\u0003auBq\u0001N\u0003\u0002\u0002\u0003\u0007\u0001(\u0001\u0004qe&\u001cW\rI\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0007\u0005\u001bE\t\u0005\u0002C\u00015\t\u0011\u0003C\u0003\"\u000f\u0001\u00071\u0005C\u00037\u000f\u0001\u0007\u0001(\u0001\u0005tCfDU\r\u001c7p)\u0005\u0001\u0014aA\"beB\u0011!IC\n\u0003\u0015m!\u0012\u0001S\u0001\u0006G>dwN]\u0001\nG>dwN]0%KF$\"\u0001\r(\t\u000fQj\u0011\u0011!a\u0001G\u000511m\u001c7pe\u0002\nQa\u001d;beR\u0004"
)
public class Car {
   private String brand;
   private double price;

   public static void start() {
      Car$.MODULE$.start();
   }

   public static void color_$eq(final String x$1) {
      Car$.MODULE$.color_$eq(var0);
   }

   public static String color() {
      return Car$.MODULE$.color();
   }

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

   public void brand_$eq(final String x$1) {
      this.brand = x$1;
   }

   public double price() {
      return this.price;
   }

   public void price_$eq(final double x$1) {
      this.price = x$1;
   }

   public void sayHello() {
      .MODULE$.println("hello");
   }

   public Car(final String brand, final double price) {
      this.brand = brand;
      this.price = price;
      super();
   }
}

        //decompiled from Car$.class
package com.doit.day01.day02;

import scala.Predef.;

public final class Car$ {
   public static Car$ MODULE$;
   private String color;

   static {
      new Car$();
   }

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

   public void color_$eq(final String x$1) {
      this.color = x$1;
   }

   public void start() {
      .MODULE$.println("
汽车启动了,嗡~~~~~~~~");
   }

   private Car$() {
      MODULE$ = this;
      this.color = "red";
   }
}

       

图示:

伴生对象用途:

  1. 可以将静态的成员变量和普通成员变量分别声明(class中没办法添加静态成员,需要经过object类来添加)
  1. 伴生对象自己内部定义了一个apply方法,可以简化创建对象(类的实例构造)
  1. 伴生对象自己定义了一个unapply方法,可以用于模式匹配

6.1.6apply方法

使用此方法时,可以在main函数中不通过new来创建一个对象,即可以不用专门的一次一次地进行实例化,加载创建对象的这个类的时候,会自动调用apply这个方法,类似Java中的static静态块。

  1. 通过伴生对象的 apply 方法,实现不使用 new 方法创建对象。 
  1. apply 方法可以重载。
  1. Scala 中 obj(arg)的语句实际是在调用该对象的 apply 方法,即 obj.apply(arg)。用以统一面向对象编程和函数式编程的风格。
  1. 当使用 new 关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实是伴生对象的 apply 方法。

Scala
object Test {
 def main(args: Array[String]): Unit = {
 //
(1)通过伴生对象的 apply 方法,实现不使用 new 关键字创建对象。
 val p1 = Person()
 println("p1.name=" + p1.name)
 val p2 = Person("bobo")
 println("p2.name=" + p2.name)
 }
}
//(2)如果想让主构造器变成私有的,可以在()之前加上 private
class Person private(cName: String) {
 var name: String = cName
}

object Person {
 def apply(): Person = {
 println("apply 空参被调用")
 new Person("xx")
 }
 
 def apply(name: String): Person = {
 println("apply 有参被调用")
 new Person(name)
}
}

6.2权限修饰符

在 Java 中,访问权限分为:public,private,protected 和默认。在 Scala 中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。

(1)Scala 中属性和方法的默认访问权限为 public,但 Scala 中无 public 关键字。

(2)private 为私有权限,只在类的内部和伴生对象中可用。

(3)protected 为受保护权限,Scala 中受保护权限比 Java 中更严格,同类、子类可以访问,同包无法访问。

(4)private[包名]增加包访问权限,包名下的其他类也可以使用

代码演示:

Scala
class Person {
 private var name: String = "bobo"
 protected var age: Int = 18
 private[test] var sex: String = "
男"
 def say(): Unit = {
 println(name)
 }
}
object Person {
 def main(args: Array[String]): Unit = {
 val person = new Person
 person.say()
 println(person.name)
 println(person.age)
 }
}
class Teacher extends Person {
 def test(): Unit = {
 this.age
 this.sex
 }
}
class Animal {
 def test: Unit = {
 new Person().sex
 }
}

6.3特质和抽象类

6.3.1特质

Trait(特质)相当于 java 的接口。比接口功能更强大。特质中可以定义属性和抽象方法和方法的实现。

Scala 的类只能够继承单一父类,但是可以实现(继承,混入)多个特质(Trait),使用的关键字是 with 和 extends

注意,特质不能有主构造函数

基本语法

Scala
trait 特质名 {
trait 主体
}

//如何使用特质:
没有父类:class 类名 extends 特质 1 with 特质 2 with 特质 3 …
有父类:class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…

代码演示:

Scala
trait PersonTrait {
 //
声明属性
 var name:String = _
 // 声明方法
 def eat():Unit={
 }
 // 抽象属性
 var age:Int
 
 // 抽象方法
 def say():Unit
}

特质的本质就是抽象类+接口

6.3.1.2特质的动态混入

1.创建对象时混入 trait,而无需使类混入该 trait

2.如果混入的 trait 中有未实现的方法,则需要实现

代码演示:

Scala
trait PersonTrait {
 //
(1)特质可以同时拥有抽象方法和具体方法
 // 声明属性
 var name: String = _
 // 抽象属性
 var age: Int
 // 声明方法
 def eat(): Unit = {
 println("eat")
 }
 // 抽象方法
 def say(): Unit
}
trait SexTrait {
 var sex: String
}
//(2)一个类可以实现/继承多个特质
//(3)所有的 Java 接口都可以当做 Scala 特质使用
class Teacher extends PersonTrait with java.io.Serializable {
 override def say(): Unit = {
 println("say")
 }
 override var age: Int = _
}
object TestTrait {
 def main(args: Array[String]): Unit = {
 val teacher = new Teacher
 teacher.say()
 teacher.eat()
 //(4)动态混入:可灵活的扩展类的功能
 val t2 = new Teacher with SexTrait {
 override var sex: String = "男"
 }
 //调用混入 trait 的属性
 println(t2.sex)
 }
}

6.3.2抽象类

在 Scala 中, 使用 abstract 修饰的类称为抽象类. 在抽象类中可以定义属性、未实现的方法(抽象方法)和具体实现的方法。  含有抽象方法的类就是抽象类

  • 抽象类中的属性 
  • 抽象方法
  • 具体实现的方法
  • 类的单继承

示例:

Scala
/*
* abstract 修饰的类是一个抽象类
* */
abstract class Animal {
  println("Animal's constructor ....")
  //
定义一个 name 属性
  val name: String = "animal"
  //
没有任何实现的方法
  def sleep()
  //
带有具体的实现的方法
  def eat(f: String): Unit = {
    println(s"$f")
    }
  }

抽象类的继承和重写

  • 如果父类为抽象类,那么子类要么也是抽象类,要么就需要重写父类中的所有的抽象方法和抽象的成员变量
  • 重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override。
  • 子类中调用父类的方法使用 super 关键字,在子类重写了父类的方法后,如果不加super,直接写方法名调用的就是子类重写后的,如果加了,调用的还是父类的
  • 子类对抽象属性进行实现,父类抽象属性可以用 var 修饰;子类对非抽象属性重写,父类非抽象属性只支持 val 类型,而不支持 var(var修饰具体方法和变量不好重写)

因为 var 修饰的为可变变量,子类继承之后就可以直接使用,没有必要重写

6.4样例类

使用case修饰的类就是样例类(封装数据,模式匹配)

  1. 构造器中的参数默认是val修饰的[成员,赋值1次]
  1. 样例类会自动创建伴生对象, 同时在里面实现;的apply和unapply方法 ,创建对象的时候不用new
  1. 很好的支持匹配模式
  1. 默认实现了自己的toString , hashCode , copy , equals,序列化方法

定义一个样例类:

Scala
case class Person(var name:String , var age:Int)
{}//
如果类中没有别的需要定义的,可以不写大括号

反编译之后的结果:

Scala
//decompiled from Person$.class
package com.doit.day01.day02;

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

public final class Person$ extends AbstractFunction2 implements Serializable {
   public static Person$ MODULE$;

   static {
      new Person$();
   }

   public final String toString() {
      return "Person";
   }

   public Person apply(final String name, final int age) {
      return new Person(name, age);
   }

   public Option unapply(final Person x$0) {
      return (Option)(x$0 == null ? .MODULE$ : new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age()))));
   }

   private Object readResolve() {
      return MODULE$;
   }

   // $FF: synthetic method
   // $FF: bridge method
   public Object apply(final Object v1, final Object v2) {
      return this.apply((String)v1, BoxesRunTime.unboxToInt(v2));
   }

   private Person$() {
      MODULE$ = this;
   }
}

        //decompiled from Person.class
package com.doit.day01.day02;

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

@ScalaSignature(
   bytes = "\u0006\u0001\u0005Uc\u0001\u0002\u000e\u001c\u0001\u0012B\u0001\"\r\u0001\u0003\u0012\u0004%\tA\r\u0005\t}\u0001\u0011\t\u0019!C\u0001\u007f!AQ\t\u0001B\tB\u0003&1\u0007\u0003\u0005G\u0001\tE\r\u0011\"\u0001H\u0011!Y\u0005A!a\u0001\n\u0003a\u0005\u0002\u0003(\u0001\u0005#\u0005\u000b\u0015\u0002%\t\u000b=\u0003A\u0011\u0001)\t\u000fU\u0003\u0011\u0011!C\u0001-\"9\u0011\fAI\u0001\n\u0003Q\u0006bB3\u0001#\u0003%\tA\u001a\u0005\bQ\u0002\t\t\u0011\"\u0011j\u0011\u001d\t\b!!A\u0005\u0002\u001dCqA\u001d\u0001\u0002\u0002\u0013\u00051\u000fC\u0004y\u0001\u0005\u0005I\u0011I=\t\u0013\u0005\u0005\u0001!!A\u0005\u0002\u0005\r\u0001\"CA\u0007\u0001\u0005\u0005I\u0011IA\b\u0011%\t\t\u0002AA\u0001\n\u0003\n\u0019\u0002C\u0005\u0002\u0016\u0001\t\t\u0011\"\u0011\u0002\u0018\u001dI\u00111D\u000e\u0002\u0002#\u0005\u0011Q\u0004\u0004\t5m\t\t\u0011#\u0001\u0002 !1q\n\u0006C\u0001\u0003[A\u0011\"!\u0005\u0015\u0003\u0003%)%a\u0005\t\u0013\u0005=B#!A\u0005\u0002\u0006E\u0002\"CA\u001c)\u0005\u0005I\u0011QA\u001d\u0011%\tY\u0005FA\u0001\n\u0013\tiE\u0001\u0004QKJ\u001cxN\u001c\u0006\u00039u\tQ\u0001Z1zaIR!AH\u0010\u0002\u000b\u0011\f\u0017\u0010M\u0019\u000b\u0005\u0001\n\u0013\u0001\u00023pSRT\u0011AI\u0001\u0004G>l7\u0001A\n\u0005\u0001\u0015Zc\u0006\u0005\u0002'S5\tqEC\u0001)\u0003\u0015\u00198-\u00197b\u0013\tQsE\u0001\u0004B]f\u0014VM\u001a\t\u0003M1J!!L\u0014\u0003\u000fA\u0013x\u000eZ;diB\u0011aeL\u0005\u0003a\u001d\u0012AbU3sS\u0006d\u0017N_1cY\u0016\fAA\\1nKV\t1\u0007\u0005\u00025w9\u0011Q'\u000f\t\u0003m\u001dj\u0011a\u000e\u0006\u0003q\r\na\u0001\u0010:p_Rt\u0014B\u0001\u001e(\u0003\u0019\u0001&/\u001a3fM&\u0011A(\u0010\u0002\u0007'R\u0014\u0018N\\4\u000b\u0005i:\u0013\u0001\u00038b[\u0016|F%Z9\u0015\u0005\u0001\u001b\u0005C\u0001\u0014B\u0013\t\u0011uE\u0001\u0003V]&$\bb\u0002#\u0003\u0003\u0003\u0005\raM\u0001\u0004q\u0012\n\u0014!\u00028b[\u0016\u0004\u0013aA1hKV\t\u0001\n\u0005\u0002'\u0013&\u0011!j\n\u0002\u0004\u0013:$\u0018aB1hK~#S-\u001d\u000b\u0003\u00016Cq\u0001R\u0003\u0002\u0002\u0003\u0007\u0001*\u0001\u0003bO\u0016\u0004\u0013A\u0002\u001fj]&$h\bF\u0002R'R\u0003\"A\u0015\u0001\u000e\u0003mAQ!M\u0004A\u0002MBQAR\u0004A\u0002!\u000bAaY8qsR\u0019\u0011k\u0016-\t\u000fEB\u0001\u0013!a\u0001g!9a\t\u0003I\u0001\u0002\u0004A\u0015AD2paf$C-\u001a4bk2$H%M\u000b\u00027*\u00121\u0007X\u0016\u0002;B\u0011alY\u0007\u0002?*\u0011\u0001-Y\u0001\nk:\u001c\u0007.Z2lK\u0012T!AY\u0014\u0002\u0015\u0005tgn\u001c;bi&|g.\u0003\u0002e?\n\tRO\\2iK\u000e\\W\r\u001a,be&\fgnY3\u0002\u001d\r|\u0007/\u001f\u0013eK\u001a\fW\u000f\u001c;%eU\tqM\u000b\u0002I9\u0006i\u0001O]8ek\u000e$\bK]3gSb,\u0012A\u001b\t\u0003WBl\u0011\u0001\u001c\u0006\u0003[:\fA\u0001\\1oO*\tq.\u0001\u0003kCZ\f\u0017B\u0001\u001fm\u00031\u0001(o\u001c3vGR\f%/\u001b;z\u00039\u0001(o\u001c3vGR,E.Z7f]R$\"\u0001^<\u0011\u0005\u0019*\u0018B\u0001<(\u0005\r\te.\u001f\u0005\b\t6\t\t\u00111\u0001I\u0003=\u0001(o\u001c3vGRLE/\u001a:bi>\u0014X#\u0001>\u0011\u0007mtH/D\u0001}\u0015\tix%\u0001\u0006d_2dWm\u0019;j_:L!a ?\u0003\u0011%#XM]1u_J\f\u0001bY1o\u000bF,\u0018\r\u001c\u000b\u0005\u0003\u000b\tY\u0001E\u0002'\u0003\u000fI1!!\u0003(\u0005\u001d\u0011un\u001c7fC:Dq\u0001R\b\u0002\u0002\u0003\u0007A/\u0001\u0005iCND7i\u001c3f)\u0005A\u0015\u0001\u0003;p'R\u0014\u0018N\\4\u0015\u0003)\fa!Z9vC2\u001cH\u0003BA\u0003\u00033Aq\u0001\u0012\n\u0002\u0002\u0003\u0007A/\u0001\u0004QKJ\u001cxN\u001c\t\u0003%R\u0019B\u0001FA\u0011]A9\u00111EA\u0015g!\u000bVBAA\u0013\u0015\r\t9cJ\u0001\beVtG/[7f\u0013\u0011\tY#!\n\u0003#\u0005\u00137\u000f\u001e:bGR4UO\\2uS>t'\u0007\u0006\u0002\u0002\u001e\u0005)\u0011\r\u001d9msR)\u0011+a\r\u00026!)\u0011g\u0006a\u0001g!)ai\u0006a\u0001\u0011\u00069QO\\1qa2LH\u0003BA\u001e\u0003\u000f\u0002RAJA\u001f\u0003\u0003J1!a\u0010(\u0005\u0019y\u0005\u000f^5p]B)a%a\u00114\u0011&\u0019\u0011QI\u0014\u0003\rQ+\b\u000f\\33\u0011!\tI\u0005GA\u0001\u0002\u0004\t\u0016a\u0001=%a\u0005Y!/Z1e%\u0016\u001cx\u000e\u001c<f)\t\ty\u0005E\u0002l\u0003#J1!a\u0015m\u0005\u0019y%M[3di\u0002"
)
public class Person implements Product, Serializable {
   private String name;
   private int age;

   public static Option unapply(final Person x$0) {
      return Person$.MODULE$.unapply(var0);
   }

   public static Person apply(final String name, final int age) {
      return Person$.MODULE$.apply(var0, var1);
   }

   public static Function1 tupled() {
      return Person$.MODULE$.tupled();
   }

   public static Function1 curried() {
      return Person$.MODULE$.curried();
   }

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

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

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

   public void age_$eq(final int x$1) {
      this.age = x$1;
   }

   public Person copy(final String name, final int age) {
      return new Person(name, age);
   }

   public String copy$default$1() {
      return this.name();
   }

   public int copy$default$2() {
      return this.age();
   }

   public String productPrefix() {
      return "Person";
   }

   public int productArity() {
      return 2;
   }

   public Object productElement(final int x$1) {
      Object var10000;
      switch(x$1) {
      case 0:
         var10000 = this.name();
         break;
      case 1:
         var10000 = BoxesRunTime.boxToInteger(this.age());
         break;
      default:
         throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
      }

      return var10000;
   }

   public Iterator productIterator() {
      return .MODULE$.typedProductIterator(this);
   }

   public boolean canEqual(final Object x$1) {
      return x$1 instanceof Person;
   }

   public int hashCode() {
      int var1 = -889275714;
      var1 = Statics.mix(var1, Statics.anyHash(this.name()));
      var1 = Statics.mix(var1, this.age());
      return Statics.finalizeHash(var1, 2);
   }

   public String toString() {
      return .MODULE$._toString(this);
   }

   public boolean equals(final Object x$1) {
      boolean var6;
      if (this != x$1) {
         label55: {
            boolean var2;
            if (x$1 instanceof Person) {
               var2 = true;
            } else {
               var2 = false;
            }

            if (var2) {
               label38: {
                  label37: {
                     Person var4 = (Person)x$1;
                     String var10000 = this.name();
                     String var5 = var4.name();
                     if (var10000 == null) {
                        if (var5 != null) {
                           break label37;
                        }
                     } else if (!var10000.equals(var5)) {
                        break label37;
                     }

                     if (this.age() == var4.age() && var4.canEqual(this)) {
                        var6 = true;
                        break label38;
                     }
                  }

                  var6 = false;
               }

               if (var6) {
                  break label55;
               }
            }

            var6 = false;
            return var6;
         }
      }

      var6 = true;
      return var6;
   }

   public Person(final String name, final int age) {
      this.name = name;
      this.age = age;
      super();
      Product.$init$(this);
   }
}

case class 和 class 的一些区别:

  1. case class 在初始化的时候,不用 new,而普通类初始化时必须要 new。
  1. case class 重写了 toString 方法。 默认实现了 equals 和 hashCode
  1. case class 实现了序列化接口 with Serializable
  1. case class 支持模式匹配(最重要的特征),所有 case class 必须要有参数列表
  1. 有参数用 case class,无参用 case object

6.5继承和多态

基本语法

class 子类名 extends 父类名 { 类体 }

(1)子类继承父类的属性和方法

(2)scala 是单继承

案例实操:

(1)子类继承父类的属性方法

(2)继承的调用顺序:父类构造器->子类构造器

Scala
class Person(nameParam: String) {
 var name = nameParam
 var age: Int = _
 def this(nameParam: String, ageParam: Int) {
 this(nameParam)
 this.age = ageParam
 println("
父类辅助构造器")
 }
 println("父类主构造器")
}
class Emp(nameParam: String, ageParam: Int) extends
Person(nameParam, ageParam) {
 var empNo: Int = _
 def this(nameParam: String, ageParam: Int, empNoParam: Int) {
 this(nameParam, ageParam)
 this.empNo = empNoParam
 println("子类的辅助构造器")
 }
  println("子类主构造器")
}
object Test {
 def main(args: Array[String]): Unit = {
 new Emp("z3", 11,1001)
 }
}

练一练:

定义一个order

属性:user_id , order_idgoods_idcategory_idpricegoods_num

需求1:对10个订单的金额大小的升序排列

需求2:对10个订单的金额大小的降序排列

需求3:统计每一种品类下的订单总额

需求4:统计每一个用户的订单总额

需求5:找出每个用户金额最大的哪个订单

需求6:找出每一种品类中金额最大的订单

需求7:找出订单金额最大的两个订单

需求8:找出订单金额最小的两个订单

7   集合

scala中的集合分为两种 ,可变集合和不可变集合, 不可变集合可以安全的并发的访问!

集合的类主要在一下两个包中

  • 可变集合包    scala.collection.mutable
  • 不可变集合包 scala.collection.immutable   默认的

Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象

可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于 java StringBuilder 对象

建议:在操作集合的时候,不可变用符号,可变用方法

scala默认使用的是不可变的集合 , 因此使用可变的集合需要导入可变集合的包

scala的集合主要分成三大类

  1. Seq 序列
  1. Set 不重复集
  1. Map 键值映射集

注意: 所有的集合都继承自Iterator迭代器这个特质

不可变集合继承图

7.1迭代器(重点)

7.1.1java中的iterator

在java中用迭代器读取文件中的数据,每次返回一行数据

Java
package com.doit;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;

class MyHero implements Iterator<String> {
    BufferedReader buffer = null;
    String line = null;

    public MyHero() {
        try {
            buffer = new BufferedReader(new FileReader("data/hero.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasNext() {
        try {
            line = buffer.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return line != null;
    }

    @Override
    public String next() {
        return line;
    }
}

public class MyIterator{
    public static void main(String[] args) {
        MyHero myHero = new MyHero();
        while (myHero.hasNext()){
            System.out.println(myHero.next());
        }
    }
}

在java中用迭代器读取mysql表中的数据,每次返回一行数据

Java
package com.doit;

import java.sql.*;
import java.util.Iterator;

public class ReadTable implements Iterator<Login> {
    ResultSet resultSet = null;
    public ReadTable(){
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/football", "root", "123456");
            PreparedStatement pps = conn.prepareStatement("select * from login ");
            resultSet = pps.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasNext() {
        boolean flag = false;
        try {
            flag = resultSet.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return flag;
    }

    @Override
    public Login next() {
        Login login = new Login();
        try {
            login.setId(resultSet.getInt(1));
            login.setUser_id(resultSet.getInt(2));
            login.setClient_id(resultSet.getInt(3));
            login.setDate(resultSet.getString(4));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return login;
    }


}


class Login {
    private int id;
    private int user_id;
    private int client_id;
    private String date;

    public Login() {
    }

    public Login(int id, int user_id, int client_id, String date) {
        this.id = id;
        this.user_id = user_id;
        this.client_id = client_id;
        this.date = date;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getUser_id() {
        return user_id;
    }

    public void setUser_id(int user_id) {
        this.user_id = user_id;
    }

    public int getClient_id() {
        return client_id;
    }

    public void setClient_id(int client_id) {
        this.client_id = client_id;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "login{" +
                "id=" + id +
                ", user_id=" + user_id +
                ", client_id=" + client_id +
                ", date='" + date + '\'' +
                '}';
    }
}

7.1.2java中的Iterable

代表可迭代的,返回的是一个迭代器

Java
package com.doit;

import java.util.Iterator;

public class ReadTableIterable implements Iterable<Login>{
    @Override
    public Iterator iterator() {
        return new ReadTable();
    }
}


//
测试
package com.doit;

import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
        ReadTableIterable logins = new ReadTableIterable();
        //可迭代的都会有一个迭代器对象,获取出来后用hasnext next获取数据
        Iterator iterator = logins.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //可迭代的java底层都封装了增强for循环,也可以直接使用
        for (Login login : logins) {
            System.out.println(login);
        }
    }
}

7.1.3scala中的 iterator

Scala
package com.doit.day01.day02

import scala.io.{BufferedSource, Source}

object MyIter {
  def main(args: Array[String]): Unit = {
    val iter: MyIter = new MyIter
    while (iter.hasNext){
      println(iter.next())
    }
  }

}

class MyIter extends Iterator[String]{
  //
读取数据
  private val source: BufferedSource = Source.fromFile("data/hero.txt")
  private val lines: Iterator[String] = source.getLines()
  //
用scala中返回迭代器中的hasNext方法直接判断
  override def hasNext: Boolean = lines.hasNext
  //
用scala中返回迭代器中的next方法获取数据
  override def next(): String = lines.next()
}

7.1.4scala中的Iterable

Scala
package com.doit.day01.day02

import scala.io.{BufferedSource, Source}

object MyIter {
  def main(args: Array[String]): Unit = {
    val iter: MyIter1 = new MyIter1
    val iterator: Iterator[String] = iter.iterator
    while (iterator.hasNext){
      println(iterator.next())
    }

    for (elem <- iter) {
      println(elem)
    }
  }
}

class MyIter1 extends Iterable[String]{
  override def iterator: Iterator[String] = new MyIter
}

7.2比较器

7.2.1java中的比较器 Comparator

Java
package com.doit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
        Order or1 = new Order("001", 100, "2022-7-12");
        Order or2 = new Order("002", 99, "2022-7-11");
        Order or3 = new Order("003", 88, "2022-7-15");
        Order or4 = new Order("004", 103, "2022-7-13");
        Order or5 = new Order("005", 55, "2022-7-10");

        ArrayList<Order> list = new ArrayList<>();
        list.add(or1);
        list.add(or2);
        list.add(or3);
        list.add(or4);
        list.add(or5);
        Collections.sort(list,new ComparatorDeme());
        System.out.println(list);
        Collections.sort(list,new ComparatorDeme1());
        System.out.println(list);
    }
}

class ComparatorDeme implements Comparator<Order>{

    @Override
    public int compare(Order o1, Order o2) {
        return -o1.getOrderAmount() + o2.getOrderAmount();
    }
}

class ComparatorDeme1 implements Comparator<Order>{

    @Override
    public int compare(Order o1, Order o2) {
        return o1.getOrderTime().compareTo(o2.getOrderTime());
    }
}

7.2.2java中的比较器 Comparable

Java
package com.doit;
//
类实现Comparable 接口,重写里面的compareTo 方法
public class Order2 implements Comparable<Order2>{
    private String orderId;
    private int orderAmount;
    private String orderTime;

    public Order2() {
    }

    public Order2(String orderId, int orderAmount, String orderTime) {
        this.orderId = orderId;
        this.orderAmount = orderAmount;
        this.orderTime = orderTime;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public int getOrderAmount() {
        return orderAmount;
    }

    public void setOrderAmount(int orderAmount) {
        this.orderAmount = orderAmount;
    }

    public String getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(String orderTime) {
        this.orderTime = orderTime;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderId='" + orderId + '\'' +
                ", orderAmount=" + orderAmount +
                ", orderTime='" + orderTime + '\'' +
                '}';
    }

    @Override
    public int compareTo(Order2 o) {
        return this.orderAmount - o.orderAmount;
    }
}

package com.doit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
//        Order or1 = new Order("001", 100, "2022-7-12");
//        Order or2 = new Order("002", 99, "2022-7-11");
//        Order or3 = new Order("003", 88, "2022-7-15");
//        Order or4 = new Order("004", 103, "2022-7-13");
//        Order or5 = new Order("005", 55, "2022-7-10");
//
//        ArrayList<Order> list = new ArrayList<>();
//        list.add(or1);
//        list.add(or2);
//        list.add(or3);
//        list.add(or4);
//        list.add(or5);
//        Collections.sort(list,new ComparatorDeme());
//        System.out.println(list);
//        Collections.sort(list,new ComparatorDeme1());
//        System.out.println(list);
//        System.out.println("===========华丽的分割线==========");

        Order2 o1 = new Order2("001", 100, "2022-7-12");
        Order2 o2 = new Order2("002", 99, "2022-7-11");
        Order2 o3 = new Order2("003", 88, "2022-7-15");
        Order2 o4 = new Order2("004", 103, "2022-7-13");
        Order2 o5 = new Order2("005", 55, "2022-7-10");

        ArrayList<Order2> list1 = new ArrayList<>();
        list1.add(o1);
        list1.add(o2);
        list1.add(o3);
        list1.add(o4);
        list1.add(o5);
        //这边就不需要再传入比较器了
        Collections.sort(list1);
        System.out.println(list1);
    }
}

7.2.3scala中的比较器 Ordering 类比于java中的Comparator

Scala
package com.doit.day01.day02

import scala.util.Sorting
   
object Demo_Ordering {
  def main(args: Array[String]): Unit = {
    val e1: Employee = new Employee(1, "
涛哥", 10000)
    val e2: Employee = new Employee(2, "
星哥", 8000)
    val e3: Employee = new Employee(3, "
行哥", 5000)
    val e4: Employee = new Employee(4, "
源哥", 3500)
    val e5: Employee = new Employee(5, "
娜姐", 2000)
    val list: Array[Employee] = List(e1, e2, e3, e4, e5).toArray
    Sorting.quickSort(list)(MyOrdering())
    println(list.mkString(","))

  }
}
case class MyOrdering() extends Ordering[Employee] {
  override def compare(x: Employee, y: Employee): Int = (x.salary - y.salary).toInt
}

class Employee(val id:Int,val name:String,val salary:Double)
  override def toString = s"Employee(id=$id, name=$name, salary=$salary)"
}

7.2.4scala中的比较器 Ordered 类比于java中的Comparable

Scala
package com.doit.day01.day02

import scala.util.Sorting

object Demo_Ordering {
  def main(args: Array[String]): Unit = {
    val e1: Employee = new Employee(1, "
涛哥", 10000)
    val e2: Employee = new Employee(2, "
星哥", 8000)
    val e3: Employee = new Employee(3, "
行哥", 5000)
    val e4: Employee = new Employee(4, "
源哥", 3500)
    val e5: Employee = new Employee(5, "
娜姐", 2000)
    val list: Array[Employee] = List(e1, e2, e3, e4, e5).toArray
    Sorting.quickSort(list)
    println(list.mkString(","))
  }
}

class Employee(val id:Int,val name:String,val salary:Double) extends Ordered[Employee]{

  override def toString = s"Employee(id=$id, name=$name, salary=$salary)"

  override def compare(that: Employee): Int = (this.salary - that.salary).toInt
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/28066.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【宝塔建站】Ubuntu下使用宝塔面板一键搭建Z-Blog个人博客

文章目录 1.前言2.网站搭建2.1. 网页下载和安装2.2.网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测试5.结语 1.前言 Ubuntu系统作…

【深度学习】pytorch pth模型转为onnx模型后出现冗余节点“identity”,onnx模型的冗余节点“identity”

情況描述 onnx模型的冗余节点“identity”如下图。 解决方式 首先&#xff0c;确保您已经安装了onnx-simplifier库&#xff1a; pip install onnx-simplifier然后&#xff0c;您可以按照以下方式使用onnx-simplifier库&#xff1a; import onnx from onnxsim import simp…

STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)

STM32F407软件模拟I2C实现MPU6050通讯&#xff08;CUBEIDE&#xff09; 文章目录 STM32F407软件模拟I2C实现MPU6050通讯&#xff08;CUBEIDE&#xff09;模拟I2C读写的实现mpu6050_iic.cmpu6050_iic.h代码分析 复位&#xff0c;读取温度&#xff0c;角度等函数封装mpu6050.cmpu…

QT学习07:五种按钮控件

文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 文章目录 抽象类&#xff1a;QAbstractButtonQPushButtonQToolButtonQCommandLinkButtonQRadioButtonQCheckBoxQButtonGroup 抽象类&#xff1a;QAbstractButton 是所有按钮类的祖先。 QAbstractButton的信号&#xff1a…

深入理解CSS字符转义行为

深入理解CSS字符转义行为 深入理解CSS字符转义行为 前言为什么要转义&#xff1f;CSS 转义什么是合法css的表达式 左半部分右半部分 练习参考链接 前言 在日常的开发中&#xff0c;我们经常写css。比如常见的按钮: <button class"btn"></button>&am…

【MySQL】 IS NOT NULL 和 != NULL 的区别?

背景 最近在开发小伙伴的需求&#xff0c;遇到了一个数据库统计的问题&#xff0c; is not null 结果正确 &#xff01;null 结果就不对&#xff0c;然后就激发了获取真理的想法&#xff0c;那必须的查查 咋回事嘞&#xff1f; 开整 在用MySQL的过程中&#xff0c;你是否存…

大学物理(上)-期末知识点结合习题复习(4)——质点运动学-动能定理 力做功 保守力与非保守力 势能 机械能守恒定律 完全弹性碰撞

目录 1.力做功 恒力作用下的功 变力的功 2.动能定理 3.保守力与非保守力 4.势能 引力的功与弹力的功 引力势能与弹性势能 5.保守力做功与势能的关系 6.机械能守恒定律 7.完全弹性碰撞 题1 题目描述 题解 题2 题目描述 题解 1.力做功 物体在力作用下移动做功…

AWS CodeWhisperer 简单介绍

一、何为AWS CodeWhisperer Amazon CodeWhisperer能够理解以自然语言&#xff08;英语&#xff09;编写的注释&#xff0c;并能实时生成多条代码建议&#xff0c; 以此提高开发人员生产力。 二、主要功能 Amazon CodeWhisperer 的主要功能&#xff0c;包括代码生成、引用追踪…

36.SpringBoot实用篇—运维

目录 一、实用篇—运维。 &#xff08;1&#xff09;程序打包与运行&#xff08;Windows版&#xff09;。 &#xff08;2&#xff09;spring-boot-maven-plugin插件作用。 &#xff08;3&#xff09;程序打包与运行&#xff08;Linux版&#xff09;。 &#xff08;4&#…

chatgpt赋能python:Python中如何处理多个输入

Python中如何处理多个输入 在编写Python程序时&#xff0c;我们经常需要从用户那里获取多个输入来执行某些操作。本文将介绍Python中的各种方法来处理多个输入。 从终端获取多个输入 Python中最简单的方式是从终端获取多个输入。下面是一个基本的例子&#xff1a; input_st…

SpringSecurity实现前后端分离登录token认证详解

目录 1. SpringSecurity概述 1.1 权限框架 1.1.1 Apache Shiro 1.1.2 SpringSecurity 1.1.3 权限框架的选择 1.2 授权和认证 1.3 SpringSecurity的功能 2.SpringSecurity 实战 2.1 引入SpringSecurity 2.2 认证 2.2.1 登录校验流程 2.2.2 SpringSecurity完整流程 2.2.…

Splashtop 与 Pax8 合作为 MSP 提供简化的远程支持解决方案

2023年4月27日 科罗拉多州丹佛 Pax8 是一个行业领先的云商务市场&#xff0c;该公司今天宣布将通过 Pax8 市场在全球推出其全新运营供应商 Splashtop。Splashtop 的远程访问、支持以及端点监控和管理解决方案极具成本效益&#xff0c;而且功能强大&#xff0c;可以助力托管服务…

002、体系结构之TiDB Server

TiDB Server 1、TiDB总览1.1、TiDB Server架构1.2、TiDB Server 主要功能&#xff1a; 2、SQL语句处理语句的解析和编译SQL层协议层上下文解析层逻辑优化器物理优化器本地执行器分布式执行器 3、如何将表的数据转成kv形式4、在线DDL相关模块5、GC机制与相关模块6、TiDB Server …

你真的会写软件测试简历吗?为什么面试约不到,测试老鸟的建议...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 写好一份简历的三…

Frida技术—逆向开发的屠龙刀

简介 Frida是一种基于JavaScript的动态分析工具&#xff0c;可以用于逆向开发、应用程序的安全测试、反欺诈技术等领域。Frida主要用于在已安装的应用程序上运行自己的JavaScript代码&#xff0c;从而进行动态分析、调试、修改等操作&#xff0c;能够绕过应用程序的安全措施&a…

mac下部署和访问 Kubernetes 仪表板(Dashboard)

简介 Dashboard 是基于网页的 Kubernetes 用户界面。 你可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中&#xff0c;也可以对容器应用排错&#xff0c;还能管理集群资源。 你可以使用 Dashboard 获取运行在集群中的应用的概览信息&#xff0c;也可以创建或者修改 Kub…

QT--配置Opencv

提示&#xff1a;本文为学习记录&#xff0c;若有疑问&#xff0c;请及时联系作者。 文章目录 前言一、下载已编译的opencv1..解压2..path路径 二、使用步骤1..pro文件2..h文件 总结 前言 只做第一个我&#xff0c;不做第二个谁。 一、下载已编译的opencv 适用于mingw编译器…

NoSQL数据库

NoSQL数据库 NoSQL简介NoSQL兴起的原因NoSQL与关系数据库的对比NoSQL的四大类型键值数据库列族数据库文档数据库图形数据库不同类型数据库比较分析RedisMongoDBCassandraNeo4j NoSQL三大基石CAPBASE最终一致性 NoSQL简介 “Not Only SQL”泛指非关系型的数据库&#xff0c;区别…

07_scrapy的应用——获取电影数据(通过excel保存静态页面scrapy爬虫数据的模板/通过数据库保存)

0、前言: 一般我们自己创建的一些python项目,我们都需要创建虚拟环境,其中会下载很多包,也叫做依赖。但是我们在给他人分享我们的项目时,不能把虚拟环境打包发送给别人,因为每个人电脑系统不同,我们可以把依赖导出为依赖清单,然后别人有了我们的依赖清单,就可以用一条…

项目使用tensorflow2会出错,下载并使用tensorflow1

背景&#xff1a;使用pycharm安装总显示安装失败&#xff0c;使用pip安装也不行&#xff0c;只能使用conda配置虚拟环境手动安装 1、下载安装anaconda 官网下载&#xff0c;双击安装。用anaconda就是想使用虚拟环境&#xff0c;万一没弄好直接删了重新搞就行。 2、创建虚拟环境…