scala学习笔记:match与unapply()
编写如下代码:
object MatchTest {
def foo(a : Any) : String =
{
a match {
case 1 => "int:1"
case x : Int if (x > 50) => "int(>50):" + x
case x : Int => "int:" + x
case (x, y) => "tuple:" + x + "," + y
case h :: t => "list:" + h + "," + t
case Array(90) => "array:90"
case Array(90, x) => "array:90," + x
case _ => ":("
}
}
def main(args : Array[String]) {
println(foo(1))
println(foo(51))
println(foo(49))
println(foo((1, 2)))
println(foo((1, 2, 3)))
println(foo((3 -> 4)))
println(foo(List(80, 81)))
println(foo(Array(90, 91)))
}
}
通过class代码反编译,看到java源代码如下:
public String foo(Object a)
{
int i = 0; int j = 0;
Object localObject1 = a;
String str;
if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(1), localObject1)) { str = "int:1"; } else {
if ((localObject1 instanceof Integer)) { i = 1; j = BoxesRunTime.unboxToInt(localObject1); if (j > 50) { str = new StringBuilder().append("int(>50):").append(BoxesRunTime.boxToInteger(j)).toString(); break label464;
}
}
if (i != 0)
{
str = new StringBuilder().append("int:").append(BoxesRunTime.boxToInteger(j)).toString();
} else if ((localObject1 instanceof Tuple2)) { Tuple2 localTuple2 = (Tuple2)localObject1; Object x = localTuple2._1(); Object y = localTuple2._2(); str = new StringBuilder().append("tuple:").append(x).append(",").append(y).toString();
} else if ((localObject1 instanceof .colon.colon)) { .colon.colon localcolon = (.colon.colon)localObject1; Object h = localcolon.head(); List t = localcolon.tl$1(); str = new StringBuilder().append("list:").append(h).append(",").append(t).toString(); } else {
if (ScalaRunTime..MODULE$.isArray(localObject1, 1)) { Object localObject2 = localObject1; Option localOption1 = Array..MODULE$.unapplySeq(localObject2); if ((!localOption1.isEmpty()) && (localOption1.get() != null) && (((SeqLike)localOption1.get()).lengthCompare(1) == 0)) { Object localObject3 = ((SeqLike)localOption1.get()).apply(0); if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(90), localObject3)) { str = "array:90"; break label464; } } }
if (ScalaRunTime..MODULE$.isArray(localObject1, 1)) { Object localObject4 = localObject1; Option localOption2 = Array..MODULE$.unapplySeq(localObject4); if ((!localOption2.isEmpty()) && (localOption2.get() != null) && (((SeqLike)localOption2.get()).lengthCompare(2) == 0)) { Object localObject5 = ((SeqLike)localOption2.get()).apply(0); Object x = ((SeqLike)localOption2.get()).apply(1); if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(90), localObject5)) { str = new StringBuilder().append("array:90,").append(x).toString(); break label464; } } }
str = ":(";
}
}
label464: return str;
}
对于h::t的写法,其解释是:
- 它其实是个中置表示法,等价于::(h,t)
- ::是一个样例类!(java里该写的类名叫.colon.colon)
再试一个简单的自定义object的例子:
object Email {
def unapply(str : String) : Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2) Some(parts(0), parts(1)) else None
}
def main(args : Array[String]) {
val str = "bluejoe2008@gmail.com"
str match {
case Email(username, host) => println(s"username: $username host: $host");
case _ => println("this is not an email address ");
}
}
}
反编译代码:
public void main(String[] args) {
String str = "bluejoe2008@gmail.com";
String str1 = str;
Option localOption = unapply(str1);
BoxedUnit localBoxedUnit;
if (localOption.isEmpty()) {
Predef..MODULE$.println("this is not an email address "); localBoxedUnit = BoxedUnit.UNIT;
}
else
{
String username = (String)((Tuple2)localOption
.get())._1(); String host = (String)((Tuple2)localOption
.get())._2(); Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "username: ", " host: ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { username, host }))); localBoxedUnit = BoxedUnit.UNIT;
}
}
如下内容摘录于http://cuipengfei.me/blog/2014/06/14/scala-unapply-method/:
unapplySeq和unapply的作用很是类似,例如这样:
object Names {
def unapplySeq(str: String): Option[Seq[String]] = {
if (str.contains(",")) Some(str.split(","))
else None
}
}
这里定义了一个unapplySeq方法,用逗号作为分隔符来把字符串拆开。然后我们可以这样应用它:
val namesString = "xiao ming,xiao hong,tom"
namesString match {
case Names(first, second, third) => {
println("the string contains three people's names")
println(s"$first $second $third")
}
case _ => println("nothing matched")
}
与上面的例子很是类似,不过编译器在这里替我们做的事情更多了:
- 调用unapplySeq,传入namesString
- 接收返回值并判断返回值是None,还是Some
- 如果是Some,则将其解开
- 判断解开之后得到的sequence中的元素的个数是否是三个
- 如果是三个,则把三个元素分别取出,赋值给first,second和third
scala学习笔记:match与unapply()的更多相关文章
- Scala学习笔记--提取器unapply
提取器就是一个带有unapply方法的对象.你可以把unapply方法当做是伴生对象中apply方法的反向操作. apply方法接收构造参数,然后将他们变成对象. 而unapply方法接受一个对象,然 ...
- 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性
基于.net的分布式系统限流组件 在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...
- Scala学习笔记及与Java不同之处总结-从Java开发者角度
Scala与Java具有很多相似之处,但又有很多不同.这里主要从一个Java开发者的角度,总结在使用Scala的过程中所面临的一些思维转变. 这里仅仅是总结了部分两种语言在开发过程中的不同,以后会陆续 ...
- Scala学习笔记之:tuple、array、Map
[TOC] 本文<快学Scala>的笔记 tuple学习笔记 tuple的定义 对偶是元组(tuple)的最简单形态--元组是不同类型的值的聚集. 元组的值是通过将单个值包含在圆括号中构成 ...
- 机器学习(三)--- scala学习笔记
Scala是一门多范式的编程语言,一种类似Java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编程和函数式编程的各种特性. Spark是UC Berkeley AMP lab所开源的类Had ...
- scala学习笔记:match表达式
写了一个超级长的表达式,估计不是最简洁的: scala> def foo(ch:Any)=ch match { case true=>"male";case false ...
- 【大数据】Scala学习笔记
第 1 章 scala的概述1 1.1 学习sdala的原因 1 1.2 Scala语言诞生小故事 1 1.3 Scala 和 Java 以及 jvm 的关系分析图 2 1.4 Scala语言的特点 ...
- 原创:Scala学习笔记(不断更新)
Scala是一种函数式语言和面向对象语言结合的新语言,本笔记中就零散记下学习scala的一些心得,主要侧重函数式编程方面. 1. 以递归为核心控制结构. 实现循环处理的方式有三种:goto,for/w ...
- Scala学习笔记(详细)
第2章 变量 val,var,声明变量必须初始化:变量类型确定后不可更改 数据类型:与java有相同的数据类型,在scala中数据类型都是对象 特殊类型:Unit:表示无值,只有一个实例值写出(),相 ...
随机推荐
- EasyUI + Spring MVC + hibernate实现增删改查导入导出
(这是一个故事--) 前言 作为一个JAVA开发工程师,我觉得最基本是需要懂前端.后台以及数据库. 练习的内容很基础,包括:基本增删改查.模糊查询.分页查询.树菜单.上传下载.tab页 主管发我一个已 ...
- Java集合的小抄 Java初学者必备
在尽可能短的篇幅里,将所有集合与并发集合的特征,实现方式,性能捋一遍.适合所有”精通Java”其实还不那么自信的人阅读. 不断更新中,请尽量访问博客原文. List ArrayList 以数组实现.节 ...
- Java HashMap 核心源码解读
本篇对HashMap实现的源码进行简单的分析. 所使用的HashMap源码的版本信息如下: /* * @(#)HashMap.java 1.73 07/03/13 * * Copyright 2006 ...
- 备份数据表为insert 脚本
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- [iOS基础控件 - 6.1] 汽车品牌列表 UITableView多项显示
A.实现思路 1.拖入UITableView 2.拖曳.连线UITableView控件 3.Controller遵守UITalbeViewDataSource协议 4.设置UITableView的da ...
- Keil MDK 5.0发布了
从上图可以看出MDK500.EXE (294,308K)分成了两部分,MDK核和software packs.MDK核跟以往一样分成四个部分,编辑器,编译器,包安装,调试跟踪.此版soft ...
- Unity3D4.x之AssetBundle学习笔记
关于AssetBundle AssetBundle可用来将多个资源打包为一个文件,实现动态下载和更新.需要注意的是Unity3D5.x以后对打包方式进行了升级,不用再在依赖关系上伤透脑筋,但是和4.x ...
- 【AwayPhysics学习笔记】:Away3D物理引擎的简介与使用
首先我们要了解的是AwayPhysics这个物理引擎并不是重头开始写的新物理引擎,而是使用Flascc技术把一个已经很成熟的Bullet物理引擎引入到了Flash中,同时为了让as3可以使用这个C++ ...
- Nodejs 动态加载 require
nodejs的require是保存在缓存中的,即require一次之后再次require值是不会改变的. 如: a.js var a = 12; exports.a = a; test.js var ...
- 使用jdbc连接上oracle的两种方法
1. 使用thin连接 优点:thin驱动都是纯Java代码,并且使用TCP/IP技术通过java的Socket连接上Oracle数据库,所以thin驱动是与平台无关的,无需安装Oracle客户端,只 ...