知识大全 面向Java开发人员的Scala指南: Scala控制结构内部揭密

Posted 语言

篇首语:春衣少年当酒歌,起舞四顾以笑和。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 面向Java开发人员的Scala指南: Scala控制结构内部揭密相关的知识,希望对你有一定的参考价值。

面向Java开发人员的Scala指南: Scala控制结构内部揭密  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  摘要 Java&# ;开发人员可以将对象作为理解 Scala 的出发点 本文是面向 Java 开发人员的 Scala 指南 系列 的第二期 作者 Ted Neward 遵循对一种语言进行评价的基本前提 一种语言的威力可以直接通过它集成新功能的能力衡量 在本文中就是指对复数的支持 跟随本文 您将了解在 Scala 中与类的定义和使用有关的一些有趣特性

  迄今为止 在此 系列 中 我们已经讨论了 Scala 对生态环境的保真度 展示了 Scala 如何将众多的 Java 核心对象功能合并在一起 如果 Scala 只是编写对象的另一种方式 那么它不会有任何引人注意的地方 或者说不再那么功能强大 Scala 的函数概念和对象概念的合并 以及它对编程人员效率的重视 这些使得学习 Scala 语言比 Java cum Scala 编程人员所想象的体验更加复杂 更加微妙

  

  关于本系列

  Ted Neward 潜心研究 Scala 编程语言 并带您跟他一起徜徉 在这个新的 developerWorks 系列 中 您将深入了解 Scala 并在实践中看到 Scala 的语言功能 在进行相关比较时 Scala 代码和 Java 代码将放在一起展示 但(您将发现)Scala 中的许多内容与您在 Java 编程中发现的任何内容都没有直接关联 而这正是 Scala 的魅力所在!毕竟 如果 Java 代码可以做到的话 又何必学习 Scala 呢?

  例如 对控制结构(比如 if while 和 for)使用 Scala 的方法 尽管这些控制结构看起来类似一些老的 还比较不错的 Java 结构 但实际上 Scala 为它们增加了一些完全不同的特性 本月的文章是关于使用 Scala 控制结构时能够期望获得哪些东西的入门级读物 而不是在制造许多错误(并编写一堆错误代码)之后 让您冒着遭受挫折的风险去寻找差异

  修订后的 Person scala

  在 本系列的上一篇文章 中 可以了解到 Scala 能够通过定义一些方法来定义 POJO 这些方法模仿基于 POJO 的环境所需的传统 getter 和 setter 在这篇文章发表之后 我收到了 Bill Venners 发来的电子邮件 Bill Venners 是即将发表的正式的 Scala 参考资料使用 Scala 编程(请参阅 参考资料)的合著者之一 Bill 指出了实现上述操作的一个更简单的方法 即使用 scala reflect BeanProperty 标注 如下所示

  清单 修改后的 Person scala

  

  class Person(fn:String ln:String a:Int)     @scala reflect BeanProperty var firstName = fn

  @scala reflect BeanProperty var lastName = ln

  @scala reflect BeanProperty var age = a

  override def toString =     [Person firstName: + firstName + lastName: + lastName +   age: + age + ]    

  清单 中的方法(上一篇文章 中的清单 的修订版)为指定的 var 生成了 get/set 方法对 惟一的缺陷是这些方法并不实际存在于 Scala 代码中 因此其他 Scala 代码无法调用它们 这通常不是什么大问题 因为 Scala 将对为自己生成的字段使用已生成的方法 如果事先不知道 那么这些对您而言可能是一个惊喜

  在查看了清单 中的代码之后 最让我感到震动的是 Scala 并没有只演示组合函数概念和对象概念的强大威力 它还演示了自 Java 首次发布之后的 年里对象语言带来的一些益处

  控制是一种幻想

  您将看到的许多奇怪的 不可思议的东西都可以归功于 Scala 的函数特性 因此 简单介绍一下函数语言开发和演变的背景可能非常有用

  在函数语言中 将越来越高级的结构直接构建到语言中是不常见的 此外 语言是通过一组核心原语结构定义的 在与将函数作为对象传递的功能结合之后 可用来定义功能的高阶函数 看起来 像是超出了核心语言的范围 但实际上它只是一个库 类似于任何库 此功能可以替换 扩充或扩展

  根据一组核心原语构建语言的合成 特性由来已久 可以追溯到 世纪 年代和 年代使用 Smalltalk Lisp 和 Scheme 的时候 诸如 Lisp 和 Scheme 之类的语言因为它们在更低级别的抽象上定义更高级别抽象的能力而受到人们的狂热追捧 编程人员可以使用高级抽象 用它们构建更高级的抽象 如今听到讨论这个过程时 它通常是关于特定于域的语言(或 DSL)的(请参阅 参考资料) 实际上 它只是关于如何在抽象之上构建抽象的过程

  在 Java 语言中 惟一选择就是利用 API 调用完成此操作 在 Scala 中 可以通过扩展语言本身实现它 试图扩展 Java 语言会带来创建极端场景(corner case)的风险 这些场景将威胁全局的稳定性 而试图扩展 Scala 则只意味着创建一个新库

  If 结构

  我们将从传统的 if 结构开始 —— 当然 此结构必须是最容易处理的结构之一 不是吗?毕竟 从理论上说 if 只检查一个条件 如果条件为真 则执行后面跟着的代码

  但是 这种简单性可能带有欺骗性 传统上 Java 语言对 if 的 else 子句的使用是随意的 并且假定如果条件出错 可以只跳过代码块 但在函数语句中 情况不是这样 为了保持函数语句的算术特性 所有一切都必须以表达式计算的方式出现 包括 if 子句本身(对于 Java 开发人员 这正是三元操作符 —— ? 表达式 —— 的工作方式)

  在 Scala 中 非真代码块(代码块的 else 部分)必须以与 if 代码块中值种类相同的形式呈现 并且必须产生同一种类的值 这意味着不论以何种方式执行代码 总会产生一个值 例如 请参见以下 Java 代码

  清单 哪个配置文件?(Java 版)

   // This is JavaString filename = default properties ;if (ntains( configFile ))  filename = (String)options get( configFile );

  因为 Scala 中的 if 结构自身就是一个表达式 所以重写上述代码会使它们成为清单 中所示的更正确的代码片段

  清单 哪个配置文件?(Scala 版)

   // This is Scalaval filename =  if (ntains( configFile ))    options get( configFile )  else    default properties

val 与 var

  您可能想更多地了解 valvar 之间的不同 实际上 它们的不同之处在于 —— 一个是只读的 另一个是可变的变量 通常 函数语言 特别是被认为是 纯 函数语言(不允许带有副作用 比如可变状态)的那些函数语言 只支持 val 概念 但是 因为 Scala 要同时吸引函数编程人员和命令/对象编程人员 所以这二种结构它都提供

  也就是说 Scala 编程人员通常应该首选 val 结构 并在明确需要可变性的时候选择 var 原因很简单 除了使编程更容易之外 val 还能确保程序的线程安全性 Scala 中的一个内在主题是 几乎每次认为需要可变状态时 其实都不需要可变状态 让我们从不可变字段和本地变量(val)开始 这是展示上述情况的一种方法 甚至对最坚定的 Java 怀疑论者也是如此 从 Java 中的 final 开始介绍可能不是很合理 或许是因为 Java 的非函数特性 尽管此原因不可取 一些好奇的 Java 开发人员可能想尝试一下

  尽管真正的赢家是 Scala 但可以通过编写代码将结果分配给 val 而不是 var 在设置之后 就无法对 val 进行更改 这与 Java 语言中 final 变量的操作方式是相同的 不可变本地变量最显著的副作用是很容易实现并发性 试图用 Java 代码实现同样的操作时 会带来许多不错的 易读的好代码 如清单 中所示

  清单 哪个配置文件?(Java 版 三元式)

   //This is Javafinal String filename =  ntains( configFile ) ?    options get( configFile ) : default properties ;

  用代码评审解释这一点可能需要点技巧 也许这样做是正确的 但许多 Java 编程人员会不以为然并且询问 您做那个干什么 ?

  已公开的 while 结构

  接下来 让我们来看一下 while 及其同胞 do while 它们做的基本上是同一件事 测试一个条件 如果该条件为真 则继续执行提供的代码块

  通常 函数语言会避开 while 循环 因为 while 实现的大多数操作都可以使用递归来完成 函数语言真地非常类似于 递归 例如 可以考虑一下 Scala by Example (请参阅 参考资料)中展示的 quicksort 实现 该实现可以与 Scala 实现一起使用

  清单 Quicksort(Java 版)

   //This is Javavoid sort(int[] xs)   sort(xs xs length );void sort(int[] xs int l int r)   int pivot = xs[(l+r)/ ];  int a = l; int b = r;  while (a <= b)    while (xs[a] < pivot) a = a + ;     while (xs[b] > pivot) b = b 每 ;     if (a <= b)       swap(xs a b);      a = a + ;      b = b 每 ;        if (l < b) sort(xs l b);  if (b < r) sort(xs a r);void swap(int[] arr int i int j)   int t = arr[i]; arr[i] = arr[j]; arr[j] = t;

  不必深入太多的细节 就可以了解 while 循环的用法 它是通过数组中的各种元素进行迭代的 先找到一个支点 然后依次对每个子元素进行排序 毫不令人奇怪的是 while 循环也需要一组可变本地变量 在这里 这些变量被命名为 a 和 b 其中存储的是当前支点 注意 此版本甚至可以在循环自身中使用递归 两次调用循环本身 一次用于对列表左手边的内容进行排序 另一次对列表右手边的内容进行排序

  这足以说明清单 中的 quicksort 真的不太容易读取 更不用说理解它 现在来考虑一下 Scala 中的直接 等同物(这意味着该版本与上述版本尽量接近)

  清单 Quicksort(Scala 版)

   //This is Scaladef sort(xs: Array[Int])   def swap(i: Int j: Int)     val t = xs(i); xs(i) = xs(j); xs(j) = t    def sort (l: Int r: Int)     val pivot = xs((l + r) / )    var i = l; var j = r    while (i <= j)       while (xs(i) < pivot) i +=       while (xs(j) > pivot) j =       if (i <= j)  swap(i j) i +=  j =               if (l < j) sort (l j)    if (j < r) sort (i r)    sort ( xs length )

  清单 中的代码看起来非常接近于 Java 版 也就是说 该代码很长 很难看 并且难以理解(特别是并发性那一部分) 明显不具备 Java 版的一些优点

  So I ll improve it ……

  清单 Quicksort(更好的 Scala 版)

   //This is Scaladef sort(xs: Array[Int]): Array[Int] =  if (xs length <= ) xs  else     val pivot = xs(xs length / )    ncat(      sort(xs filter (pivot >))            xs filter (pivot ==)       sort(xs filter (pivot <))) 

  显然 清单 中的 Scala 代码更简单一些 注意递归的使用 避免完全 while 循环 可以对 Array 类型使用 filter 函数 从而对其中的每个元素应用 greater than equals 和 less than 函数 事实上 在引导装入程序之后 因为 if 表达式是返回某个值的表达式 所以从 sort() 返回的是 sort() 的定义中的(单个)表达式

  简言之 我已经将 while 循环的可变状态完全再次分解为传递给各种 sort() 调用的参数 —— 许多 Scala 狂热爱好者认为这是编写 Scala 代码的正确方式

  可能值得一提的是 Scala 本身并不介意您是否使用 while 代替迭代 —— 您会看到来自编译器的 您在干什么 在做蠢事吗? 的警告 Scala 也不会阻止您在可变状态下编写代码 但是 使用 while 或可变状态意味着牺牲 Scala 语言的另一个关键方面 即鼓励编写具有良好并行性的代码 只要有可能并且可行 Scala 式作风 会建议您优先在命令块上执行递归

  编写自己的语言结构

  我想走捷径来讨论一下 Scala 的控制结构 做一些大多数 Java 开发人员根本无法相信的事 —— 创建自己的语言结构

  那些通过死读书学习语言的书呆子会发现一件有趣的事 while 循环(Scala 中的一个原语结构)可能只是一个预定义函数 Scala 文档以及假设的 While 定义中对此进行了解释说明

   // This is Scaladef While (p: => Boolean) (s: => Unit)   if (p) s ; While(p)(s)

  上述语句指定了一个表达式 该表达式产生了一个布尔值和一个不返回任何结果的代码块(Unit) 这正是 while 所期望的

  扩展这些代码行很容易 并且可以根据需要使用它们 只需导入正确的库即可 正如前面提到的 这是构建语言的综合方法 在下一节介绍 try 结构的时候 请将这一点牢记于心

  再三尝试

  try 结构允许编写如下所示代码

  清单 如果最初没有获得成功……

   // This is Scalaval url =  try     new URL(possibleURL)    catch     case ex: MalformedURLException =>      new URL( ) 

  清单 中的代码与 清单 或 清单 中 if 示例中的代码相差甚远 实际上 它比使用传统 Java 代码编写更具技巧 特别是在您想捕获不可变位置上存储的值的时候(正如我在 清单 中最后一个示例中所做的那样) 这是 Scala 的函数特性的又一个优点!

  清单 中所示的 case ex 语法是另一个 Scala 结构(匹配表达式)的一部分 该表达式用于 Scala 中的模式匹配 我们将研究模式匹配 这是函数语言的一个常见特性 稍后将介绍它 现在 只把它看作一个将用于 switch/case 的概念 那么哪种 C 风格的 struct 将用于类呢?

  现在 再来考虑一下异常处理 众所周知 Scala 支持异常处理是因为它是一个表达式 但开发人员想要的是处理异常的标准方法 并不仅仅是捕获异常的能力 在 AspectJ 中 是通过创建方面(aspect)来实现这一点的 这些方面围绕代码部分进行联系 它们是通过切入点定义的 如果想让数据库的不同部分针对不同种类异常采取不同行为 那么必须小心编写这些切入点 —— SQLExceptions 的处理应该不同于 IOExceptions 的处理 依此类推

  在 Scala 中 这只是微不足道的细节 请留神观察!

  清单 一个自定义异常表达式

  

  // This is Scalaobject Application  def generateException()      System out println( Generating exception );    throw new Exception( Generated exception ); 

  def main(args : Array[String])      tryWithLogging  // This is not part of the language          generateException        System out println( Exiting main() ); 

  def tryWithLogging (s: => _)     try       s        catch       case ex: Exception =>        // where would you like to log this? // I choose the console window for now ex printStackTrace()     

  与前面讨论过的 While 结构类似 tryWithLogging 代码只是来自某个库的函数调用(在这里 是来自同一个类) 可以在适当的地方使用不同的主题变量 不必编写复杂的切入点代码

  此方法的优点在于它利用了 Scala 的捕获一级结构中横切逻辑的功能 —— 以前只有面向方面的人才能对此进行声明 清单 中的一级结构捕获了一些异常(经过检查的和未经检查的都包括)并以特定方式进行处理 上述想法的副作用非常多 惟一的限制也许就是想象力了 您只需记得 Scala 像许多函数语言一样允许使用代码块(aka 函数)作为参数并根据需要使用它们即可

   for 生成语言

  所有这些都引导我们来到了 Scala 控制结构套件的实际动力源泉 for 结构 该结构看起来像是 Java 的增强 for 循环的简单早期版 但它远比一般的 Java 编程人员开始设想的更强大

  让我们来看一下 Scala 如何处理集合上的简单顺序迭代 根据您的 Java 编程经验 我想您应该非常清楚该怎么做

  清单 对一个对象使用 for 循环和对所有对象使用 for 循环

   // This is Scalaobject Application  def main(args : Array[String])      for (i < to ) // the left arrow means assignment in Scala      System out println( Counting + i) 

  此代码所做的正如您期望的那样 循环 次 并且每次都输出一些值 需要小心的是 表达式 to 并不意味着 Scala 内置了整数感知(awareness of integer)以及从 到 的计数方式 从技术上说 这里存在一些更微妙的地方 编译器使用 Int 类型上定义的方法 to 生成一个 Range 对象(Scala 中的任何东西都是对象 还记得吗?) 该对象包含要迭代的元素 如果用 Scala 编译器可以看见的方式重新编写上述代码 那么该代码看起来很可能如下所示

  清单 编译器看见的内容

   // This is Scalaobject Application  def main(args : Array[String])      for (i < to( )) // the left arrow means assignment in Scala      System out println( Counting + i) 

  实际上 Scala 的 for 并不了解那些成员 并且并不比其他任何对象类型做得更好 它所了解的是 scala Iterable scala Iterable 定义了在集合上进行迭代的基本行为 提供 Iterable 功能(从技术上说 它是 Scala 中的一个特征 但现在将它视为一个接口)的任何东西都可以用作 for 表达式的核心 List Array 甚至是您自己的自定义类型 都可以在 for 中使用

  特殊性

  正如上面已经证明的那样 for 循环可以做许多事情 并不只是遍历可迭代的项列表 事实上 可以使用一个 for 循环在操作过程中过滤许多项 并在每个阶段都产生一个新列表

   让 Scala 与英语更接近

  您可能已经注意到 理解清单 中的 Scala 的 for 循环版本更容易一些 这要感谢 Range 对象暗中将两端都包含在内 以下英语语言语法比 Java 语言更接近些 假如有一条 Range 语句说 from to do this 那么这意味着不再产生意外的 off by one 错误

  清单 看一看还有哪些优点

   // This is Scalaobject Application  def main(args : Array[String])      for (i < to ; i % == )      System out println( Counting + i) 

  注意到清单 中 for 表达式的第二个子句了吗?它是一个过滤器 实际上 只有那些传递给过滤器(即计算 true)的元素 向前传给 了循环主体 在这里 只输出了 到 的偶数数字

  并不要求 for 表达式的各个阶段都成为过滤器 您甚至可以将一些完全平淡无奇的东西(从循环本身的观点来看)放入管道中 例如以下代码显示了在下一个阶段进行计算之前的 i 的当前值

  清单 让我如何爱上您呢?别那么冗长

  

  // This is Scalaobject App  def log(item : _) : Boolean =      System out println( Evaluating + item)    true 

  def main(args : Array[String]) =      for (val i < to ; log(i); (i % ) == )      System out println( Counting + i) 

  在运行的时候 范围 到 中的每个项都将发送给 log 它将通过显式计算每个项是否为 true 来 批准 每个项 然后 for 的第三个子句将对这些项进行筛选 过滤出那些满足是偶数的条件的元素 因此 只将偶数传递给了循环主体本身

  简单性

  在 Scala 中 可以将 Java 代码中复杂的一长串语句缩短为一个简单的表达式 例如 以下是遍历目录查找所有 scala 文件并显示每个文件名称的方法

  清单 Finding scala

   // This is Scalaobject App  def main(args : Array[String]) =      val filesHere = (new java io File( )) listFiles    for (      file < filesHere;      if file isFile;      if file getName endsWith( scala )    ) System out println( Found + file) 

  这种 for 过滤很常见(并且在此上下文中 分号很让人讨厌) 使用这种过滤是为了帮助您做出忽略分号的决定 此外 Scala 允许将上述示例中的圆括号之间的语句直接作为代码块对待

  清单 Finding scala(版本 )

   // This is Scalaobject App  def main(args : Array[String]) =      val filesHere = (new java io File( )) listFiles    for       file < filesHere      if file isFile      if file getName endsWith( scala )    System out println( Found + file) 

  作为 Java 开发人员 您可能发现最初的圆括号加分号的语法更直观一些 没有分号的曲线括号语法很难读懂 幸运的是 这两种句法产生的代码是等效的

  一些有趣的事

  在 for 表达式的子句中可以分配一个以上的项 如清单 中所示

  清单 名称中有什么?

  

  // This is Scalaobject App  def main(args : Array[String]) =      // Note the array initialization syntax; the type (Array[String])    // is inferred from the initialized elements    val names = Array( Ted Neward Neal Ford Scott Davis       Venkat Subramaniam David Geary )

  for       name < names      firstName = name substring( name indexOf( ))    System out println( Found + firstName) 

  这被称为 中途赋值(midstream assignment) 其工作原理如下 定义了一个新值 firstName 该值用于保存每次执行循环后的 substring 调用的值 以后可以在循环主体中使用此值

  这还引出了嵌套 迭代的概念 所有迭代都位于同一表达式中

  清单 Scala grep

  

  // This is Scalaobject App  def grep(pattern : String dir : java io File) =      val filesHere = dir listFiles    for (      file < filesHere;      if (file getName endsWith( scala ) || file getName endsWith( java ));      line < scala io Source fromFile(file) getLines;      if line trim matches(pattern)    ) println(line) 

  def main(args : Array[String]) =      val pattern = *object *

  grep pattern new java io File( ) 

  在此示例中 grep 内部的 for 使用了两个嵌套迭代 一个在指定目录(其中每个文件都与 file 连接在一起)中找到的所有文件上进行迭代 另一个迭代在目前正被迭代的文件(与 line 本地变量连接在一起)中发现的所有行上进行迭代

  使用 Scala 的 for 结构可以做更多的事 但目前为止提供的示例已足以表达我的观点 Scala 的 for 实际上是一条管道 它在将元素传递给循环主体之前处理元素组成的集合 每次一个 此管道其中的一部分负责将更多的元素添加到管道中(生成器) 一部分负责编辑管道中的元素(过滤器) 还有一些负责处理中间的操作(比如记录) 无论如何 Scala 会带给您与 Java 中引入的 增强的 for 循环 不同的体验

  匹配

  今天要了解的最后一个 Scala 控制结构是 match 它提供了许多 Scala 模式匹配功能 幸运的是 模式匹配会声明对某个值进行计算的代码块 首先 将执行代码块中最接近的匹配结果 因此 在 Scala 中可以包含以下代码

  清单 一个简单的匹配

   // This is Scalaobject App  def main(args : Array[String]) =      for (arg < args)      arg match  case Java => println( Java is nice ) case Scala => println( Scala is cool ) case Ruby => println( Ruby is for wimps ) case _ => println( What are you a VB programmer? )       

  刚开始您可能将 Scala 模式匹配设想为支持 String 的 开关 带有通常用作通配符的下划线字符 而这正是典型开关中的默认情况 但是 这样想会极大地低估该语言 模式匹配是许多(但不是大多数)函数语言中可以找到的另一个特性 它提供了一些有用的功能

  对于初学者(尽管这没什么好奇怪的) 可能认为 match 表达式自身会产生一个值 该值可能出现在赋值语句的右边 正如 if 和 try 语句所做的那样 这一点本身也很有用 但匹配的真正威力体现在基于各种类型进行匹配时 而不是如上所述匹配单个类型的值 或者更多的时候 它是两种匹配的组合

  因此 假设您有一个声明返回 Object 的函数或方法 —— 在这里 Java 的 java lang reflect Method invoke() 方法的结果可能是一个好例子 通常 在使用 Java 语言计算结果时 首先应该确定其类型 但在 Scala 中 可以使用模式匹配简化该操作

  清单 您是什么?

  

  //This is Scalaobject App  def main(args : Array[String]) =      // The Any type is exactly what it sounds like: a kind of wildcard that    // accepts any type    def describe(x: Any) = x match       case => five       case true => truth       case hello => hi!       case Nil => the empty list       case _ => something else    

  println describe( )    println describe( hello ) 

  因为 match 的很容易简单明了地描述如何针对各种值和类型进行匹配的能力 模式匹配常用于解析器和解释器中 在那里 解析流中的当前标记是与一系列可能的匹配子句匹配的 然后 将针对另一系列子句应用下一个标记 依此类推(注意 这也是使用函数语言编写许多语言解析器 编译器和其他与代码有关的工具的部分原因 这些函数语言中包括 Haskell 或 ML)

  关于模式匹配 还有许多可说的东西 但这些会将我们直接引导至 Scala 的另一个特性 case 类 我想将它留到下次再介绍

  结束语

  Scala 在许多方面看起来都非常类似于 Java 但实际上只有 for 结构存在一些相似性 核心语法元素的函数特性不仅提供了一些有用的特性(比如已经提到的赋值功能) 还提供了使用新颖有趣的方式扩展语言的能力 不必修改核心 javac 编译器本身 这使该语言更加符合 DSL 的定义(这些 DSL 是在现有语言的语法中定义的) 并且更加符合编程人员根据一组核心原语(a la Lisp 或 Scheme)构建抽象的愿望

cha138/Article/program/Java/hx/201311/25727

相关参考

知识大全 面向Java开发人员的Scala指南: 面向对象的函数编程

面向Java开发人员的Scala指南:面向对象的函数编程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下

知识大全 面向Java开发人员的Scala指南: 实现继承

面向Java开发人员的Scala指南:实现继承  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  S

知识大全 面向Java开发人员的Scala指南: 增强Scitter库

面向Java开发人员的Scala指南:增强Scitter库  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 面向Java开发人员的Scala指南: 深入了解Scala并发性 了解 Scala 如何简化并发编

面向Java开发人员的Scala指南:深入了解Scala并发性了解Scala如何简化并发编  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后

知识大全 面向Java开发人员的Scala指南: 关于特征和行为

面向Java开发人员的Scala指南:关于特征和行为  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 面向Java开发人员的Scala指南: 包和访问修饰符

面向Java开发人员的Scala指南:包和访问修饰符  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 面向Java开发人员的Scala指南: 构建计算器,第1 部分

面向Java开发人员的Scala指南:构建计算器,第1部分  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 面向Java开发人员的Scala指南: 构建计算器,第 2 部分

面向Java开发人员的Scala指南:构建计算器,第2部分  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一

知识大全 面向Java开发人员的Scala指南: 深入了解Scala并发性 了解 actor 如何提供新的应

面向Java开发人员的Scala指南:深入了解Scala并发性了解actor如何提供新的应  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后

知识大全 Java开发者的Scala指南: Scala+Twitter=Scitter

Java开发者的Scala指南:Scala+Twitter=Scitter  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我