Scala学习笔记(一)

Scala

学习链接,绝对好用

package chapter01
object Hello {
  //scala源码中包含了main方法,在编译后自动形成了public static void main
  //Scala在编译源码时,会生成两个字节码文件,静态main方法执行另外一个字节码文件中的成员main方法
  //scala是完全面向对象的语言,没有静态的方法,只能通过模拟生成静态方法
  //编译时将当前类生成一个特殊的类==》Scala01_HelloWord$,然后创建对象来调用这个对象的main方法
  //一般情况下,将加$的类的对象,称之为“半生对象”
  //伴生对象中的内容,都可以通过类名访问,来模拟Java中的静态语法
  //伴生对象语法规则:使用object声明
  //scala中没有public关键字,默认所有的访问权限都是公共的。
  //scala中没有void关键字,采用特殊的对象模拟:Unit
  //scala中声明方法采用关键字def
  //方法后面的小括号是方法的参数列表
  //scala中的参数列表的声明方式和Java不一样
  //java:String 参数名
  //scala: 参数名 :类型
  //java 中方法的声明和方法直接连接
  //scala中将方法的返回值类型放置在方法声明的后面使用冒号连接
  def main(args: Array[String]): Unit = {
    println("Hello Word")
  }
}
package chapter01

object Scala02_StringPrint {
  def main(args: Array[String]): Unit = {
    //打印字符串
    println("打印字符串")
    //变量
    val name = "ApacheCN"
    val age = 1
    val url = "www.atguigu.com"
    print("name=" + name + "age=" + age + "url=" + url + "\n")
    printf("name=%s,age=%d,url=%s\n", name, age, url)
    //插值字符串
    println(s"name=${name},age=${age},url=${url}")
    //格式化
    print(f"name=${name},age=${age}%.2f,url=${url}\n")
    //原值
    println(raw"name=${name},age=${age}%.2f,url=${url}\n")
       //多行字符串
    val s=
      """
        |jfasjdflasjf
        |fsaldjfsklafj
        |fasfjas
        |fdklgjdsfgj
        |""".stripMargin
    print(s)
  }
}

在这里插入图片描述

变量的声明

object Scala01_Var {

  def main(args: Array[String]): Unit = {
    var name: String = "张三"
    //声明变量
    //var 变量名称:变量类型=变量的值
    //使用var声明的变量的值是可以修改的
    //scala声明变量必须显示的初始化
    
    //错误
    /*
    var name:String
    name="张三"
     */
    var age: Int = 10
    var c: Char = 'c'
    var d: Double = 12
    var b: Boolean = true
    age = 20
    name = "李四"

    //使用val声明的变量的值不可以修改
    //在方法的外部声明的变量如果采用val关键字,等同于使用final修饰
    val name1: String = "Zhangsan"
    //name1="lisi" 错误
  }
}
object VarValDemo1 {
  def main(args: Array[String]): Unit = {
    var a:Int=10;
    a=20
    print(a)

    val b:Int=100
    print(b)

    var c =10//scala的类型推导
    //a=1l 报错

    /*
    注意:在Scala中,能用常量的地方不要用变量
    2、在声明的同时给变量和常量赋值
    3、
     */
  }
}

变量命名规则

package chapter02

object NameRegular {
  //命名规则
  def main(args: Array[String]): Unit = {
    val ++ = 10
    print(++)
    //val a++ =10
    val a_++ =10
    val ` ` =30//空格作为变量名
    val `type` =2
  }
}
/*
标识符(常量,变量,对象,方法,函数)命名规范:
1、使用Java的命名规则
        Scala中的下划线要慎用
2、不用使用$
        将来Scala编译的时候,一些类会自动添加$
3、支持使用运算符(+-/*...)来命名标识符
         在Scala中没有真正的运算符,所有的运算符其实都是对象的方法
         a:不要使用单个运算符作为变量名和常量
         b:字符和运算符不能混用
                a++不允许
         c:如果混用,可以用_隔开
4、可以使用``定义任意字符,主要为了兼容Java中的一些标识符名
 */

数据输入

package chapter02

import java.io.{BufferedReader, InputStreamReader}
import java.util.Scanner

import scala.io.StdIn

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

    //java的写法
    //1、高级写法
    val scan:Scanner= new Scanner(System.in)
    println(scan.nextLine())
    //2、把标准输入流转换成字符流(低级写法)
    val reader :BufferedReader=new BufferedReader(new InputStreamReader(System.in,"utf-8"))
    val line:String =reader.readLine()
    println(line)

    //Scala的写法
    val line1=StdIn.readLine()
    println(line1)

    val line2=StdIn.readLine("请输入:")//"请输入“会被先打印出后输入
    println(line2)
  }
}

数据转换

package chapter02

object Type {
  def main(args: Array[String]): Unit = {
    val a:Long=1
    val b:Double=2
    val c:Double=a
    val d=b.toInt
    val s="123"
    val i=Integer.parseInt(s)
    val i1=s.toInt
    println()
  }
}
/*
Byte
Short
Long
Int
Float
        自动转换(提升):
            byte->short->float->double
            char->int
        强制转换类:
            java:(int)1L
            scala:
                   .toInt
 */

运算符

package chapter02

object Operator1 {
  def main(args: Array[String]): Unit = {
    val r:Int=1.+(2)
    println(r)
    println(1+3)
    val s=10
    var i=1
    i+=1
    println(i)

    val a="a"
    val b=a+"b"
    val c=a+"b"

    println(b==c)//true
    println(b.equals(c))//true
    println(b.eq(c))//false

    
  }
}
  /*
  运算符
      在Scala中,没有真正的运算符,所谓运算符,其实是一个方法(函数)名!
      +-/都是方法名
      1、在Scala中,调用方法的点,可以省略
      2、在给方法传递参数的时候,如果这个方法的参数只有一个参数或者没有参数,则括号也可以省略
      ++ --这两个垃圾运算符被去掉

      scala:
           ==等价于equals
           equals等价于==
               自定义类型应该重写equals
           eq 等价于Java中的==

   */
数据类型描述
Unit表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Nullnull , Null 类型只有一个实例值null
NothingNothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。 当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性)
package chapter02

import scala.io.StdIn

object IfDemo {
  def main(args: Array[String]): Unit = {
    val m=10
    val n=20
    val max=if(m>n)m else n
    println(max)
      
    val i=if(m>n){
      100
    }else 1
      
    println(i)

    var d=10
    d=30
    println(d=40)//()
    val q=90
    val s:Double=Math.pow(q,2)
    println(s)
  }
}
/*
重要:
    在Scala中,任意的语法结构(执行的语句,表达式等等)都有值!
    是执行的最后一样代码的值自动返回
    注意:
        1、在Scala中,赋值的语句的值是Unit
 */
/*
流程控制
     1、顺序流程
     2、分支
           if
             和Java中的完全一致
           模式匹配
              替换掉Java中的switch,语法有点像,但是远远超过Java的switch
     3、循环
 */

for循环

object For1 {
  def main(args: Array[String]): Unit = {
    val a:String="abc"//字符串
    //遍历容器 c只读,不能改
    for(c <-a){
      println(c)
    }

    //使用for输出1-100
    for(i <- 1.to(100)){
      print(i+" ")
    }
    println()

    //使用for输出1-100的所有奇数
    for(i <- 1 to(100,2)){//to有两个参数,参数1就是结束的值,参数2是布长;
      print(i+" ")
    }
    println()
    for(i <- 1 to 100 by 2){
      print(i +" ")//效果同上
    }
    println()

    //使用for输出 100-1
    for(i <-1 to 100 reverse){
      print(i+" ")
    }
    println()


  }
}
/*
Scala中的for循环,本质是一种遍历,遍历集合(容器)中的每个元素,
当遍历完最后一个元素之后,自动终止
1、如果要使用for,必须先有容器
2、
 */
 
object For2 {
  def main(args: Array[String]): Unit = {
    //输出1-100的奇数
    for (i <- 1 to 100 if (i % 2 == 1)) {
      print(i + " ")
    }
    println()
    //
    for (i<- 0 until 100){//[0,100)
      print(i+" ")
    }
    println()

    //引入其它变量
    for (i <- 1 to 100 if(i % 2==0);j=i*i if(j<1000);k=j*j){
      println(s"i=$i,j=$j,k=$k")
    }
    
  }
}

在这里插入图片描述

终止for循环

package chapter03

import scala.io.StdIn
import scala.util.control.Breaks._

object For3 {
  def main(args: Array[String]): Unit = {
    val n = StdIn.readInt()
    var isPrime = true
    /*    try {
             for (i <- 2 until n) {
               if (n % i == 0) {
                 isPrime = false
                 throw new IllegalArgumentException
               }
             }
           } catch {
             case _ =>
    }*/
    //或
    //结束循环:本质是自己抛异常,再去捕捉异常
    //while ,do while ,for 都可以使用
    breakable {
      for (i <- 2 until n) {
        if (n % 2 == 0) {
          isPrime = false
          break()
        }
      }
    }

    if (isPrime) {
      println(s"$n 是一个质数")
    } else {
      println(s"$n 不是一个质数")
    }


  }
}

/*
Scala中没有break关键字
 */

for嵌套循环

package chapter03

object For4 {
  def main(args: Array[String]): Unit = {
    //9*9乘法表
    for (i <- 1 to 9) {
      for (j <- 1 to i) {
        print(s"$j*$i=${i * j}\t")
      }
      println()
    }
    
    println()

    for (i <- 1 to 9; j <- 1 to i) {//所有的代码都在内循环,则可以使用的嵌套
        //实际使用很少
      print(s"$j*$i=${i * j}\t")
      if (i == j) println()
    }
  }
}

函数至简原则:能省则省

1至简原则细节

(1)return可以省略,Scala会使用函数体的最后一行代码作为返回值

(2)返回值类型如果能够推断出来,那么可以省略

(3)如果函数体只有一行代码,可以省略花括号

(4)如果函数无参,则可以省略小括号。若定义函数时省略小括号,则调用该函数时,也需省略小括 号;若定时函数时未省略,则调用时,可省可不省。

(5)如果函数明确声明Unit,那么即使函数体中使用return关键字也不起作用

(6)Scala如果想要自动推断无返回值,可以省略等号

(7)如果不关心名称,只关系逻辑处理,那么函数名(def)可以省略

(8)如果函数明确使用return关键字,那么函数返回就不能使用自行推断了,需要声明返回值类型

高阶函数

package chapter04

object Function_1 {
  //函数:入参(方法参数),出参(返回值)
  def main(args: Array[String]): Unit = {
    println(add(1,2,4))
    println(add(1,c=2))//按照参数名传递参数
    println(add(c=10,a=1,b=32))//按照参数名传递参数
    println(test())

    foo(f)

    def add(a:Int ,b:Int=3,c:Int)=a+b+c

    def test() = "Test"

    def f()={
      println("a")
    }

    def foo(x:() => Unit)={
      println(x)
      x()
    }

  }
  /*
  1、函数可以定义在任何位置
     可以在函数内定义函数
  2、可以把函数当成一个值返回给函数的调用者,
     函数的调用者就可以在函数的外部去调用这个返回的函数
  3、可以把函数当作一个值,传递给另外一个函数
  4、如果一个函数可以返回一个函数作为返回值,或者可以接收一个(多个)函数作为参数
     那么这个函数就称为高阶函数
   */
}

匿名函数

package chapter04

object Function_2 {
  def main(args: Array[String]): Unit = {
    val a=()=>println("aaa")
   // foo( ()=>{println("匿名函数")} )

    foo((a:Int,b:Int)=>a+b)//或foo((a,b)=>a+b)
    foo(_+_)//第一个下划线表示第一个参数,类推
  }


  def foo(add:(Int,Int)=>Int)={
    println(add(10, 20))
  }

  /*
  def foo(f:()=>Unit)={
    f()
  }
  */

}
/*
匿名函数:
    没有名字的函数,就是匿名函数
    用处:
        1、作为实参,直接传递给高阶函数
        2、直接作为高级函数的返回值
2、传递:
      foo((a:Int,b:Int)=>a+b)
3、在传递匿名函数的时候,参数的类型一般可以利用上下文,让Scala自动去推导
4、foo(_+_)
    要求:1、匿名只能有两个函数
         2、每个参数只使用一次
         3、第一个_表示第一个参数,第二个下划线表示第二个参数
 */
package chapter04

object Function_4 {
  def main(args: Array[String]): Unit = {
    //遍历
    val arr = Array(30, 50, 73, 60, 11, 20)
    foreach(arr, a => println(a))
    //使用给定的条件,对数组过滤
    val arr2=filter(arr,x=>x%2==0)
    foreach(arr2,println)

    val arr3=map(arr,x=>x*x)
    foreach(arr3,println)

    println(reduce(arr, (x:Int, y:Int) => {
      println(s"x=$x,y=$y")
      x + y
    }))

  }
  def map(arr:Array[Int],op:Int => Int)={
    for (elem <- arr) yield op(elem)
  }

  def foreach(arr: Array[Int], op: Int => Unit) = {
    for(elem<- arr){
      op(elem)
    }
  }
  def filter(arr:Array[Int],condition:Int=>Boolean)={
    for(elem <- arr;if condition(elem))yield elem
  }

  def reduce(arr:Array[Int],op:(Int,Int)=>Int):Int={
    var sum=0;
    for (elem <- arr) {
      sum=op(sum,elem)
    }
    sum
  }
}

/*
经典的高阶函数
foreach
     遍历集合中的每个元素
filter
     过滤,过滤条件可以通过一个返回boolean的函数来体现
map
     映射,一进一出
reduce
     聚合操作
     1 to 100

 */

在这里插入图片描述

闭包

package chapter04

object Closure {
  def main(args: Array[String]): Unit = {
    def f:Int=>Int=foo()//!
    val r:Int=f(10)//能够访问到a,是因为闭包的存在
    println(r)

    def f1=foo1()
    println(f1())
    println(f1())
    val f2=foo1()
    println(f2())

  }
  def foo():Int=>Int={
    var a=10
    (b:Int)=>a+b
  }
  def foo1()={
    var a=10
    ()=>{a+=1;a}
  }

}
/*
闭包:
   一个函数,如果访问了外部的局部变量,则这个函数和它访问的局部变量,称为一个闭包
   闭包会阻止外部局部变量的销毁,可以把局部变量的使用延伸到函数的外部
 */

面向对象

package chapter05

import scala.annotation.meta.beanGetter
import scala.beans.BeanProperty

object ObjectDemo_1 {
  def main(args: Array[String]): Unit = {
    val user = new User()
    println(user)
    println(user.age)
    user.eat()
    user.age_$eq(100) // <=> user.age=100
    println(user.age)
    user.name_("haha")
    user.setAge(32)
    println(user)

  }
}

class User {
  //定义属性
  @BeanProperty  var age = 10
  private var name="xugao"
  val country = "china"
  private var a1 = 100

  //类定义方法
  def eat(): Unit = {
    println("eat" + this.name)
  }
  def name_(name:String): Unit ={
    this.name=name
  }

  override def toString = s"User($age, $name, $country)"
  //自己写的
/*  def getAge(){
    age
  }

  def setAge(age: Int): Unit = {
    this.age = age
  }*/

}

/*
Scala默认的getter和setter不满足JavaBean规范
     getAge()   setAge(...)
     需要注解,Scala会自动生成get、set

 */

构造器

package chapter05

import scala.beans.BeanProperty

object Obj_3{
  def main(args: Array[String]): Unit = {
    val person=new User2(10,"xu","男")
    val user=new User2()
    println(user.age)
    //给类取别名
    type U=User2
    val u=new U()
    println(u.age)
    println(u.getClass.getName)//获得类名

  }

}
class User2(@BeanProperty var age:Int, var name:String, var sex:String){
  //辅助构造器
  def this(){
    //首行必须调用主构造器
    this(10,"abc","male")//构造器内调用构造器
  }
  def this(c:Int){
    this()//调用前面的构造器
  }
  var a=10
  def eat ={
    println(sex)
    this.age
  }
}
/*
1、调用构造器创建对象,可以给属性赋值
2、在类名的后面添加需要的一些属性,这些在创建对象的时候,可以给这些属性赋值
3、类名后面跟的其实就是构造器,这个就是主构造器,一个类唯一一个
4、def this()
        首行必须是调用主构造器
        辅助构造器的参数,仅仅是一个只能在当前的这个辅助构造器内使用的普普通的一个常量
5、后面的辅助构造器可以调用前面的,前面的不能调用后面的
 */

包的导入

package chapter06
//import java.util._ //导入util下的所有类
//import java.util.HashMap
//import java.util.TreeMap
//import java.util.{TreeMap,HashMap} 导入TreeMap和HashMap
//导包的时候给类取别名
import java.util.{HashMap=>HM}
//不用HashMap,但用util下的其他类
import java.util.{TreeMap=>_,_}

私有化构造器

package chapter06

object Modifier_1 {
  def main(args: Array[String]): Unit = {
    val user=new User(1)
    println(user.a)
  }
}
//构造器私有
class User private[chapter06](var age:Int){//该构造器只能在chapter06下调用
  private [chapter06] val a:Int=10
  private val b:Int=2
}

继承

package chapter06

import java.awt.im.InputMethodRequests

object Extends_1 {
  def main(args: Array[String]): Unit = {
    new B(1).foo()
  }
}
class A(val a:Int){
  def this(){
    this(2)
  }
  println("A 主构造器")
  def foo()={
    println("A foo")
  }
}
class B(val b:Int) extends A{//可以调用辅助构造器
  println("B 主构造器")
  override def foo()={
    super.foo()
    println("B foo")
  }
}
/*
1、scala 是单继承
2、Scala没有接口,但是提供了更加强的trail(特质)
 注意:
     1、复写方法,必须添加关键字 override
     2、构造器的特征
     先执行父类的构造器,然后才是子类的构造器
        父的主构造器->子类的主构造器->...->子类构造器
属性的复写
   1、val 只能复写 val 和不带参数的def
   2、var 只能复写抽象的 var
 */

在这里插入图片描述

属性覆写

package chapter06

object Extends_2 {
  def main(args: Array[String]): Unit = {
    val b=new B
    println(b.a)
  }
}
class A{
var a:Int=10
}
class B extends A {
  override val a:Int=20
}

抽象类

package chapter06

object Abs1 {
  def main(args: Array[String]): Unit = {
    val a:A=new B
    a.foo()
  }
  abstract class A(var a:Int){
    //属性只声明,不初始化,这就是抽象字段
    var b:Int
    //方法只有声明,没有实现,就是抽象方法
    def foo():Int
  }
  class B() extends A(2){
    override var b: Int = _
    override def foo(): Int ={
      println("hello")
      1
    }
  }
/*
scala的抽象类可以有哪些成员:
1、普通类可以有的,抽象类都可以
2、抽象类可以有抽象方法和抽象字段(属性)
3、抽象类不能够创建对象
 */

}

匿名内部类

伴生类、伴生对象

package chapter06

object Abs2 {
  def main(args: Array[String]): Unit = {
    //创建一个匿名内部类的对象
    val a=new C(20) {
      override var b: Int = 2

      override def foo(): Int = 4
    }
    println(a.b)
  }
}
abstract class C(var a:Int){
  var b:Int
  def foo():Int
}

单例设计

package chapter06

object Single1 {
  def main(args: Array[String]): Unit = {
    D.foo
    D()//等价于D.apply()
  }
}
object D{
  def foo=println("foo...")
  def apply():Int={
    println("apply")
    10
  }

}

class D{

}
/*
scala中单例
     使用object关键字,声明出来的对象就是一个单例对象
     独立对象
     任何的对象(object,也可以是new),只要提供了一个apply方法,都可以
     像使用方法一样去调用对象

     如果在同一个.scala文件中,一个object的名字和一个class的名字一样,则他们
     分别叫伴生类和伴生对象
     编译成字节码之后,伴生对象的是静态方法,伴生类是非静态(对象方法)
 */

在这里插入图片描述

trait

package chapter07

import java.util.logging.Logger

object Trait_1 {
  def main(args: Array[String]): Unit = {
    val usb: Usb = new HuaweiUsb
    usb.insert
    usb.work
    usb.pop
  }
}
class Logger{
  println("logger 类的构造器")
  def print()={
    println("开始打印日志...")
  }
}
trait Usb {
  println("Usb 类的构造器 第一个混入的")
  //抽象字段
  val name: String

  def insert: Unit

  def work: Unit

  def pop: Unit

  def init() = {
    println("usb 开始初始化...")
  }
}

trait MyException {
  println("MyException 的构造器 第二个混入")
  def throwExec: Exception
}

class HuaweiUsb extends Logger  with Usb with MyException  {
  override val name: String = "huawei"

  override def insert: Unit = {
    println("华为 usb开始插入...")
    init()
  }

  override def work: Unit = {
    println("华为 usb开始工作...")
    print()
  }

  override def pop: Unit = {
    println("华为 usb退出工作...")
  }

  override def throwExec: Exception = new RuntimeException("usb出现异常")
}

/*
scala:
    scala没有提供接口,但是提供了更加强大的:trait特质
    1、抽象类中有的东西,trait都可以有
           抽象类是累,只能单继承
           trait 可以多继承
    2、当类继承类和trail,对前面用extends,后面的统一用with(混入)

*/

多混入问题

package chapter07

object Trait_2 {
  def main(args: Array[String]): Unit = {
    val abc =new ABC
    abc.foo()

    println("***************")
    val my=new My with A with B//动态混入
    my.foo()
  }
}
class My{

}
class ABC extends A with B with C{
  override def foo(): Unit = {
    super.foo()
    println("ABC...")
  }
}
trait A{
  def foo()={
    println("A...")
  }
}
trait B extends A{
  override def foo()={
    println("B...")
  }
}
trait C extends A{
  override def foo() ={
    super[A].foo()//如果没有[A]则按混入顺序往前找,调用的是B中的foo方法
    println("C...")
  }
}
/*
1、如果一个类混入的特质中有相同的实现好的方法,则会产生成员冲突
2、可以使用菱形的继承结构解决冲突问题,冲突解决之后,方法是最后混入的那个
3、super[A] super具体指代
4、动态混入(叠加)
 */

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值