Scala是一种运行在Java虚拟机上,集成面向对象编程和函数式编程的多范式编程语言。许多之前用java开发关键业务的公司正在转向scala,以此加速开发效率,应用程序的延展性以及可靠性。
Scala有一些不同于java的新特性,主要有以下几点:
l 所有类型都是对象
l 类型推断
l 嵌套函数
l 函数也是对象
l 支持DSL(领域专用语言)
l Traits
l 闭包
l 支持并发
接下来我们用一些代码实例来更直观地了解下scala相较于java的优点:
1. 用scala写的代码将会更简洁
你不需要getters和setters,case类提供了许多功能(看以下例子)。相较于java7,甚至java8,scala的集合使用起来也会更加紧凑。
Java:
public class Person implements Serializable {
private String firstName;
private String lastName;
private String email;
private String password;
public Person(
String firstName, String lastName,
String email, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean equals(Object o) {
…
}
@Override
public int hashCode() {
…
}
@Override
public String toString() {
…
}
}
Scala:
case class Person(
var firstName: String,
var lastName: String,
var email: String,
var password: String)
2. Scala有强大的模式匹配
在Java中你基本上只能匹配原型类型(byte, short, char, int, String, enum),例如:
public class Main {
public static void main(String[] args) {
int i = 123;
switch (i) {
case 1:
System.out.println("Matched 1");
}
}
}
但是在Scala中你几乎可以匹配一切,例如:
class Main extends App {
abstract class Animal
case class Cat(name: String) extends Animal
case class Dog(age: Int) extends Animal
val something: Object = new Dog(3)
something match {
// 匹配数字:
case 123 => println("Found integer 123")
// 匹配其中一个值:
case -10 | 0 | 10 => println("Found -10, 0, or 10")
// 匹配一个可以是任何值的数字:
case i: Int => println("Found an int")
// 匹配任何Dog类型对象:
case dog: Dog => println("Found a Dog")
// 匹配10岁的Dog对象:
case Dog(10) => println("Found a 10 year's old Dog")
// 匹配任何Dog对象, 并且获取其年龄:
case Dog(age) if age > 3 => println("Found a Dog with age > 3")
// 匹配任何大于3岁的Dog对象, 并且获取其年龄:
case Dog(age) => println("Found a Dog with age: " + age)
// 匹配任何动物:
case animal: Animal => println("Found an animal")
}
}
3. 每个文件可以有多个类
在Java中,类有更多的样板代码,加上每个文件只有一个public的类,因此没有那么容易定位和维护代码。
Scala则允许一个文件里有多个类,并且有着更简短的语法。可以想象下以下代码如果用java开发会有多少文件和代码行数:
abstract class Person {
val id: Long
val name: String
}
case class Employee(
id: Long,
name: String,
salary: Double
) extends Person
case class Customer(
id: Long,
name: String,
email: String
) extends Person
case class Payment(
id: Long,
customer: Customer,
responsible: Employee,
submittedDate: Date,
lastModifiedDate: Date,
value: Double
)
case class Project(
id: Long,
budget: Double,
customer: Customer,
manager: Employee,
team: Seq[Employee]
)
case class ProjectFile(
id: Long,
projectId: Long,
filename: String,
size: Long
)
4. 更好的集合
Java8极大地改善了java集合,但是和scala比起来仍旧显得笨拙,如下:
public class Main {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John Doe", 26),new Person("Jane Doe", 21),new Person("Mike", 28),new Person("Anne", 16), new Person("John", 14));
Map<Character, List<String>> firstLetterIndex =
persons.stream()
.map(p -> p.getName())
.sorted()
.collect(Collectors.groupingBy(it -> it.charAt(0)));
// 该变量不能被修改, 否则不能和filter一起使用:
final Integer adultAge = 18;
List<Person> adults = persons.stream().filter(p -> p.getAge() >= adultAge).collect(Collectors.toList());
Integer sumOfAges = persons.stream().map(p -> p.getAge()).reduce(0, (a1, a2) -> a1 + a2);
}
static class Person {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
}
}
Scala的集合会有更短的代码:
class Main extends App {
val persons = List(
new Person("John Doe", 26),
new Person("Jane Doe", 21),
new Person("Mike", 28),
new Person("Anne", 16),
new Person("John", 14))
val firstLetterIndex =
persons.map(_.name).sorted.groupBy(_.charAt(0))
// scala中, 该变量会被修改,并且仍旧在filter中使用:
var adultAge = 18
val adults = persons.filter(_.age >= adultAge)
val sumOfAges = persons.map(_.age).foldLeft(0)(_ + _)
case class Person(name: String, age: Int)
}
5. Traits
Traits展现了scala极好的模块化和重用性。他们提供了一种安全的多继承,并且包含了方法实现和状态。
class Main extends App {
trait Animal { var weight: Double; def move(): Unit }
// Traits可以包含方法:
trait FlyingAnimal extends Animal { def move() = println("I'm flying!") }
trait WalkingAnimal extends Animal { def move() = println("I'm walking!") }
// (Traits方法可以被覆写):
trait FlyingWalkingAnimal extends FlyingAnimal with WalkingAnimal {
override def move() = println("I'm flying, or walking maybe!")
}
// Traits可以包含状态:
trait ColoredAnimal extends Animal { val color: String }
trait LightColorAnimal extends ColoredAnimal { val color = "light" }
trait DarkColorAnimal extends ColoredAnimal { val color = "dark" }
trait HeavyAnimal extends Animal { var weight = 100d }
trait LightAnimal extends Animal { var weight = 20d }
trait AnimalInZoo
// 你可以继承多个traits:
class Lion extends WalkingAnimal with HeavyAnimal with LightColorAnimal
class Dog extends WalkingAnimal with LightAnimal with DarkColorAnimal
class Seagull extends FlyingWalkingAnimal with LightAnimal with LightColorAnimal
class Eagle extends FlyingAnimal with LightAnimal with DarkColorAnimal
val wildLion = new Lion()
// 该lion实例在动物园中!:
val zooLion = new Seagull() with AnimalInZoo
}
Java8虽然为接口引进了default method,但是不够强大,比如说他们不能包含状态。
6. scala更多的其他特性
还有许多非常实用的特性。以下例子展示了lazy vals,默认参数,命名参数,多行string,等:
class Main extends App {
var displayAge = false
// 该值只有在被使用时才会被计算:
lazy val averageAgeInUSA = {
Thread.sleep(1000) /* 访问数据库... */
35
}
// 因为displayAge是false, 所以值不会被计算
if (displayAge) {
println("Average age is: " + averageAgeInUSA)
}
class Image(
// 方法, 构造方法,
// 可以有默认值:
colorMode: String = "RGBA",
width: Int = 800,
height: Int = 600,
autoScaling: Boolean = false
)
val img1 = new Image() /* <-- 所有都用默认值 */
val img2 = new Image("CMYK") /* <-- colorMode不用默认值*/
// 可以用名称传递参数:
val img3 = new Image(autoScaling = true) /*<-- autoScaling不用默认值*/
println(s"""Scala allows you to have
|multiline strings, and even
|using variables directly in those
|strings with string interpolation.
|Like this: $displayAge.
|""".stripMargin)
}
Scala的一个经典使用案例就是Spark应用的开发。Apache Spark框架是用scala开发的,可以用java或者scala开发应用。但是使用scala会更加便捷,高效。

点击回顾往期精彩内容
当RX遇上Spring——Spring 5新特性之响应式Web应用
想了解更多请关注我们



