本文概述
- Scala与Java:哪个更复杂?
- 一个类示例:Java vs. Scala
- 我们公平吗?
- 进一步举例说明
- 动态与静态
- 本文总结
Scala是一种类型安全的JVM语言, 它将面向对象的程序和函数式编程都结合到一种极其简洁, 逻辑且功能强大的语言中。有些人可能会惊讶地发现Scala并不像他们想象的那么新, 它于2003年首次推出。但是, 尤其是在过去的几年中, Scala才开始获得大量关注。这就引出了” 为什么要使用Scala?” 的问题。
本文研究了Scala的优势, 尤其是与Java相比(因为Scala编写为在JVM中运行)。 Scala不是创建” 更好的Java” 的唯一尝试。诸如Kotlin和Ceylon之类的替代方案也走了这条路, 但他们做出了一个基本决定, 即在语法上保持与Java语言本身非常接近, 以最大程度地减少学习时间。这似乎是一个不错的主意, 但最终还是有些自欺欺人, 因为它迫使你停留在许多完全相同的Java范式中, 这些范式就是首先要创建” 更好的Java” 的原因。
相比之下, Scala的创建目的是成为一种更好的语言, 以摆脱Java认为对开发人员来说过于严格, 过于繁琐或令人沮丧的那些方面。结果, 确实存在代码差异和范式转换, 这可能会使Scala编程的早期学习变得更加困难, 但是结果是一种更加简洁和井井有条的语言, 最终更易于使用并提高了生产率。
文章图片
Scala与Java:哪个更复杂? 具有讽刺意味的是, 虽然Java语言的简单性是其成功的一部分, 但它也为其复杂性做出了贡献。当然, 你几乎可以用Java编写任何东西, 但是这样做所需的代码行可能令人生畏。另一方面, Scala中的编程结构稍微复杂一些。但是, 如果你可以编写稍微复杂一点的单行代码来代替Java的20条” 更简单” 的行, 那么哪一行真的更复杂?
事实是Java通常太冗长了。在Scala中, 编译器非常聪明, 因此避免了开发人员需要明确指定编译器可以推断的内容。比较一下这个简单的” Hello World!” Java vs. Scala中的程序:
Java中的Hello World:
public class HelloJava {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
斯卡拉的Hello World:
object HelloScala {
def main(args: Array[String]): Unit = {
println("Hello World!")
}
}
尽管此处的两种语言之间并没有很大的区别, 但即使在这个简单的示例中, Scala的详细程度也较低。
举一个更实际的例子, 让我们看一下创建一个简单的字符串列表:
Java:
List<
String>
list = new ArrayList<
String>
();
list.add("1");
list.add("2");
list.add("3");
规模:
val list = List("1", "2", "3")
当然, Java中有一些技巧可以缩短代码, 但在标准用法中却不行。
现在考虑一种情况, 我们有一个数字字符串列表, 但我们希望将该列表转换为整数列表:
Java:
List<
Integer>
ints = new ArrayList<
Integer>
();
for (String s : list) {
ints.add(Integer.parseInt(s));
}
规模:
val ints = list.map(s =>
s.toInt)
借助Scala的功能特性, 这种转换变得非常简单。
一个类示例:Java vs. Scala 让我们更进一步, 比较Java和Scala中的标准Bean /普通旧Java对象(PO??JO)创建。
首先, Java版本:
public class User {
private String name;
private List<
Order>
orders;
public User() {
orders = new ArrayList<
Order>
();
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public List<
Order>
getOrders() {
return orders;
}public void setOrders(List<
Order>
orders) {
this.orders = orders;
}
}public class Order {
private int id;
private List<
Product>
products;
public Order() {
products = new ArrayList<
Product>
();
}public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public List<
Product>
getProducts() {
return products;
}public void setProducts(List<
Product>
products) {
this.products = products;
}
}public class Product {
private int id;
private String category;
public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public String getCategory() {
return category;
}public void setCategory(String category) {
this.category = category;
}
}
ew Lotta代码。
现在是Scala版本:
class User {
var name: String = _
var orders: List[Order] = Nil
}class Order {
var id: Int = _
var products: List[Product] = Nil
}class Product {
var id: Int = _
var category: String = _
}
我们说哪种语言比较复杂?
我们公平吗? 如果你到现在为止都是Java程序员, 那么你可能会认为我在对代码进行不公平的比较。毕竟, 没有什么能阻止我使用Java创建公共变量, 然后摆脱getter和setter。
但是, 如果你回想一下Java中的getter和setter背后的原因, 那么它专门用于将来的验证。也就是说, 如果以后需要在获取或设置变量时添加一些逻辑, 则必须重新编写那些公共变量以使用方法(这就是Java中鼓励使用getter和setter开头的原因。 )。但是, 在Scala编程中并非如此。由于采用了语言设计, 因此抽象无需使用getter和setter即可保持完整。例如, 考虑一下Scala中经过修改的User类, 如果你尝试将名称设置为null, 则会抛出NullPointerException:
class User {
private var _name: String = _
var orders: List[Order] = Nil
def name = _name
def name_=(name: String) = {
if (name == null) {
throw new NullPointerException("User.name cannot be null!")
}
_name = name
}
你仍然可以像这样设置名称:
user.name = "John Doe"
【Scala与Java(为什么要学习Scala())】请注意, 这完全消除了预先配置方法访问器的需要。
而且, 由于Scala更喜欢不变性, 因此我可以使用case类更简洁地在Scala中编写此代码:
case class User(name: String, orders: List[Order])
case class Order(id: Int, products: List[Product])
case class Product(id: Int, category: String)
太疯狂了, 我要写的代码少了多少。
进一步举例说明 现在考虑上述类的场景, 我想在User类中添加一个漂亮的小方法, 该方法返回用户订购的所有产品的列表:
在Java的冗长世界中:
public List<
Product>
getProducts() {
List<
Product>
products = new ArrayList<
Product>
();
for (Order order : orders) {
products.addAll(order.getProducts());
}
return products;
}
幸运的是, java.util.List有一个addAll方法, 否则在Java中getProducts()可能更长。
另一方面, 在Scala中, 我们需要做的是:
def products = orders.flatMap(o =>
o.products)
你会看到Scala语言实现的规模要小得多。是的, 对于Scala新手来说, 它似乎更加复杂, 但是一旦你真正理解了其背后的概念, Scala代码将比Java代码看起来更加简单。
让我们变得更加复杂。如果我们只想获取特定类别中的产品怎么办?
在这种情况下, 我们无法利用java.util.List中的addAll方法, 因此Java中的情况变得更糟:
public List<
Product>
getProductsByCategory(String category) {
List<
Product>
products = new ArrayList<
Product>
();
for (Order order : orders) {
for (Product product : order.getProducts()) {
if (category.equals(product.getCategory())) {
products.add(product);
}
}
}
return products;
}
但是, 在Scala中, 代码仍然相当简单。我们只需要使用flatMap即可将拼合在一起的每个Order的产品列表合并到一个列表中, 然后进行过滤以仅包括与类别匹配的产品:
def productsByCategory(category: String) = orders.flatMap(o =>
o.products).filter(p =>
p.category == category)
动态与静态 在过去的几年中, 当然不缺少新语言, 但是尽管最近出现的几乎所有其他语言都是动态的, 但是Scala是静态类型的。
作为专业的开发人员(尽管我知道并使用许多动态语言), 我认为编译时检查对于编写可靠的代码非常重要。在动态语言中, 除非你在各种情况下实际运行它, 否则你将永远无法确保自己的代码没有足够的错误和健壮性。这可能导致代码中潜在的严重缺陷, 直到代码投入生产后才可能实现。
本文总结 希望本文将Java与Scala进行了充分的融合, 以使你对Scala的功能和能力有初步的了解, 并激发了你学习该语言的兴趣。它不仅是一种很棒的语言, 它可以使编程变得不那么乏味并且更加有趣, 而且还被世界上一些最大的公司(LinkedIn, Twitter, FourSquare, The Guardian等)使用。
Scala开发人员的空缺职位数量不断增加, 证明了Scala的受欢迎程度和使用量正在迅速上升。如果你还没有这样做的话, 那么现在将是一个开始尝试并停止询问” 为什么要学习Scala?” 的好时机。
推荐阅读
- CakePHP 3评论–仍然新鲜,仍然很热
- 逆向工程软件专用API的教程(破解你的Couch)
- Buggy CakePHP代码(CakePHP开发人员最常犯的6个错误)
- 从头开始(我如何构建开发人员的梦想键盘)
- 分离焦虑(使用Linux命名空间隔离系统的教程)
- 完美的地图(使用D3.js制作精美的Web地图)
- 电子游戏物理教程-第二部分(实体物体的碰撞检测)
- 面向Web开发人员的最佳在线映射工具的调查(路线图)
- MIDI教程(创建由MIDI硬件控制的基于浏览器的音频应用程序)