下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者。正因如此,下划线这个特殊符号无形中增加Scala的入门难度。本文希望帮助初学者踏平这个小山坡。

1. 用于替换Java的等价语法

由于大部分的Java关键字在Scala中拥有了新的含义,所以一些基本的语法在Scala中稍有变化。

1.1 导入通配符

*在Scala中是合法的方法名,所以导入包时要使用_代替。

  1.  
    //Java
  2.  
    import java.util.*;
  3.  
     
  4.  
    //Scala
  5.  
    import java.util._

1.2 类成员默认值

Java中类成员可以不赋初始值,编译器会自动帮你设置一个合适的初始值:

  1.  
    class Foo{
  2.  
    //String类型的默认值为null
  3.  
    String s;
  4.  
    }
  5.  
     

而在Scala中必须要显式指定,如果你比较懒,可以用_让编译器自动帮你设置初始值:

  1.  
    class Foo{
  2.  
    //String类型的默认值为null
  3.  
    var s: String = _
  4.  
    }
  5.  
     

该语法只适用于类成员,而不适用于局部变量。

1.3 可变参数

Java声明可变参数如下:

  1.  
    public static void printArgs(String ... args){
  2.  
    for(Object elem: args){
  3.  
    System.out.println(elem + " ");
  4.  
    }
  5.  
    }

调用方法如下:

  1.  
    //传入两个参数
  2.  
    printArgs("a", "b");
  3.  
    //也可以传入一个数组
  4.  
    printArgs(new String[]{"a", "b"});
  5.  
     

在Java中可以直接将数组传给printArgs方法,但是在Scala中,你必须要明确的告诉编译器,你是想将集合作为一个独立的参数传进去,还是想将集合的元素传进去。如果是后者则要借助下划线:

printArgs(List("a", "b"): _*)
 

1.4 类型通配符

Java的泛型系统有一个通配符类型,例如List<?>,任意的List<T>类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:

  1.  
    public static void printList(List<?> list){
  2.  
    for(Object elem: list){
  3.  
    System.out.println(elem + " ");
  4.  
    }
  5.  
    }
  6.  
     

对应的Scala版本为:

  1.  
    def printList(list: List[_]): Unit ={
  2.  
    list.foreach(elem => println(elem + " "))
  3.  
    }
  4.  
     

2 模式匹配

2.1 默认匹配

  1.  
    str match{
  2.  
    case "1" => println("match 1")
  3.  
    case _ => println("match default")
  4.  
    }
  5.  
     

2.2 匹配集合元素

  1.  
    //匹配以0开头,长度为三的列表
  2.  
    expr match {
  3.  
    case List(0, _, _) => println("found it")
  4.  
    case _ =>
  5.  
    }
  6.  
     
  7.  
    //匹配以0开头,长度任意的列表
  8.  
    expr match {
  9.  
    case List(0, _*) => println("found it")
  10.  
    case _ =>
  11.  
    }
  12.  
     
  13.  
    //匹配元组元素
  14.  
    expr match {
  15.  
    case (0, _) => println("found it")
  16.  
    case _ =>
  17.  
    }
  18.  
     
  19.  
    //将首元素赋值给head变量
  20.  
    val List(head, _*) = List("a")
  21.  
     

3. Scala特有语法

3.1 访问Tuple元素

  1.  
    val t = (1, 2, 3)
  2.  
    println(t._1, t._2, t._3)

3.2 简写函数字面量(function literal)

如果函数的参数在函数体内只出现一次,则可以使用下划线代替:

  1.  
    val f1 = (_: Int) + (_: Int)
  2.  
    //等价于
  3.  
    val f2 = (x: Int, y: Int) => x + y
  4.  
     
  5.  
    list.foreach(println(_))
  6.  
    //等价于
  7.  
    list.foreach(e => println(e))
  8.  
     
  9.  
    list.filter(_ > 0)
  10.  
    //等价于
  11.  
    list.filter(x => x > 0)
  12.  
     

3.3 定义一元操作符

在Scala中,操作符其实就是方法,例如1 + 1等价于1.+(1),利用下划线我们可以定义自己的左置操作符,例如Scala中的负数就是用左置操作符实现的:

  1.  
    -2
  2.  
    //等价于
  3.  
    2.unary_-

3.4 定义赋值操作符

我们通过下划线实现赋值操作符,从而可以精确地控制赋值过程:

  1.  
    class Foo {
  2.  
    def name = { "foo" }
  3.  
    def name_=(str: String) {
  4.  
    println("set name " + str)
  5.  
    }
  6.  
     
  7.  
    val m = new Foo()
  8.  
    m.name = "Foo" //等价于: m.name_=("Foo")

3.5 定义部分应用函数(partially applied function)

我们可以为某个函数只提供部分参数进行调用,返回的结果是一个新的函数,即部分应用函数。因为只提供了部分参数,所以部分应用函数也因此而得名。

  1.  
    def sum(a: Int, b: Int, c: Int) = a + b + c
  2.  
    val b = sum(1, _: Int, 3)
  3.  
    b: Int => Int = <function1>
  4.  
    b(2) //6

3.6 将方法转换成函数

Scala中方法和函数是两个不同的概念,方法无法作为参数进行传递,也无法赋值给变量,但是函数是可以的。在Scala中,利用下划线可以将方法转换成函数:

  1.  
    //将println方法转换成函数,并赋值给p
  2.  
    val p = println _
  3.  
    //p: (Any) => Unit

4. 小结

下划线在大部分的应用场景中是以语法糖的形式出现的,可以减少击键次数,并且代码显得更加简洁。但是对于不熟悉下划线的同学阅读起来稍显困难,希望通过本文能够帮你解决这个的困惑。

--------------------- 本文来自 CODE男孩 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_24084925/article/details/79041595?utm_source=copy

Scala下划线_使用的更多相关文章

  1. scala中的下划线_

    1.作为“通配符”,类似Java中的*. 例如 import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理! 例如 val s = sum(1 to 5 ...

  2. Scala 神奇的下划线 _

    引言 在 Scala 中,下划线 _ 有很多种用法,作为 Scala 初学者也经常被下划线 _ 搞得晕头转向,下面是对 Scala 中下划线 _ 使用的简单总结~ 导包时, 下划线 _ 表示引用多个方 ...

  3. scala下划线的用法

    1.作为“通配符”,类似Java中的*.如import scala.math._2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就是 ...

  4. css命名为何不推荐使用下划线_

    一直习惯了在命名CSS样式名时使用下划线“_”做为单词的分隔符,这也是在写JS时惯用的写法. 用过CSS hack的朋友应该知道,用下划线命名也是一种hack,如使用“_style”这样的命名,可以让 ...

  5. 修改 Pattern代码使 Java 正则表达式支持下划线 '_'

    为什么 由于工作是做数据ETL的,很多时候会使用到正则对数据进行提取,但是java的正则中的groupname不支持'_',官方的文档中是这样的: Group name A capturing gro ...

  6. Python 私有变量中两个下划线 _ _item 与 一个下划线的区别 _item

    python中没有常量的说法, 但是可以通过元组实现一个常量 在python的私有变量中, 存在两个下划线 _ _item 与一个下划线 _item 的区别 前面带两个下划线的私有变量: 只能在本类中 ...

  7. python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名

    python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名,如果在类中定义的就是类的私有成员. >>> dir(__builtin ...

  8. 为什么我不建议在C#中用下划线_开头来表示私有字段

    我在C#官方文档的使用属性里看到这种代码: public class Date { private int _month = 7; // Backing store public int Month ...

  9. scala下划线

    作为函数的参数 一个匿名的函数传递给一个方法或者函数的时候,scala会尽量推断出参数类型.例如一个完整的匿名函数作为参数可以写为 scala> def compute(f: (Double)= ...

随机推荐

  1. 从mysql读取数据写入mongo

    # coding:utf-8 # Created by qinlin.liu at 2017/3/14 import pymysql import datetime #pymongo说明文档  : h ...

  2. python验证代理IP

    接上一篇保存的IP地址,进行验证 # -*- coding: utf-8 -*- import requests from threading import Thread import threadi ...

  3. NAND Flash vs NOR Flash

    Avinash Aravindan reference:https://www.embedded.com/design/prototyping-and-development/4460910/2/Fl ...

  4. 基于MicroBlaze 的嵌入式系统设计

       reference: http://xilinx.eetrend.com/d6-xilinx/article/2013-03/3863.html 摘 要:当今时代,嵌入式系统已经无所不在,与人们 ...

  5. centos tar 常用

    tar命令详解 -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用 ...

  6. 获得本机Ip地址

  7. MERGE INTO 解决大数据量 10w 更新缓慢的问题

    有个同事处理更新数据缓慢的问题,数据量超10w的量,更新速度太慢耗时较长,然后改成了 MERGE INTO 效率显著提高. 使用方法如下 MERGE INTO 表A USING 表B ON 关联条件 ...

  8. ylz 开发学习笔记一(注意事项)

    Eclipse快捷键 断点 F6执行下一步 等等 C+S+R 搜索文件名字      C+鼠标移动左击 跳入类文件    jsp 文件的断点是使用 debugger  之后再chrom 用F10单步调 ...

  9. L268 A terrifying look at the consequences of climate change

    Climate change is a devilish problem for humanity: at once urgent and slow-moving, immediate and dis ...

  10. Qt 查询字符串数据

    (1)函数QString::startsWith(),判断某一个字符串是否以某个字符串开头:该函数具有两个参数,第一个参数制定了一个字符串,第二个参数指定是否大小写敏感,默认大小写敏感: eg: QS ...