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:表示无值,只有一个实例值写出(),相 ...
随机推荐
- MVC Razor 语法(转)
http://blog.csdn.net/pasic/article/details/7072340 原文地址:MVC Razor 语法(转)作者:panzhaowen_jacki 语法名称 Razo ...
- android学习之activity
Activity 的生命周期 和 J2ME 的 MIDlet 一样,在 android 中,Activity 的生命周期交给系统统一管理.与 MIDlet 不同的是安装在 android 中的所有的 ...
- Linux PHP实现仿百度文库预览功能
1.安装openoffice: tar zxvf OOo_3.3.0_Linux_x86-64_install-rpm-wJRE_zh-CN.tar.gzcd RPEMrpm -ivh *.rpm安装 ...
- BNUOJ-29365 Join in tasks 简单数学
题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=29365 首先排序,然后维护一个后缀,等差求下和就可以了.. //STATUS:C++_AC ...
- Java 多线程同步的五种方法
一.引言 闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子 ...
- 自定义文件上传的按钮的样式css+js
核心就是一段css遮住了原生的input框,然后用js将文件的值传入到另一个指定的input框中 原文链接 http://geniuscarrier.com/how-to-style-a-html-f ...
- NSTimer、 NSTask、 NSThread 和 NSRunloop 之间的区别
NSTimer是一个计时器对象,方法调用在对未来的选择对象. NSThread是一个线程类. 也就是创建一个线程. NSTask类是一个过程,一种方式运行程序从您的其他程序. NSOperation是 ...
- 手把手教你入门mac idea
一.前沿 去年入职后, 公司有很多人使用的是idea , 而不是eclipse. 之前就想转向idea, 但一直没转过来~~原因是团队的人提倡用开源eclipse.现在下定决心转向idea. 虽然, ...
- Android studio中出现非法字符时的部分解决方法
我将原来在Eclipse中开发的工程搬到了Android studio上来,在运行,编译程序的过程中出现了错误.提示存在非法字符. 后来发现是由于程序代码中有中文字符的出现,问题就出在对中文支持的UT ...
- HBase 和 MongoDB在设计上的区别
转载:http://leongfans.iteye.com/blog/1019383 昨天搜一下mongodb的资料,介绍应用的比较多,原理介绍的不多. 粗略得看了一下,总体来说两者的设计思路差不多, ...