第3章——从Java到Scala
你可以在使用 Scala 的同时运用自己的 Java 技能。在某些方面 Scala 与 Java 类似,但在 许多其他方面又彼此不同。Scala 青睐纯面向对象,但它又尽可能将类型和 Java 的类型对应 起来。Scala 在支持熟悉的命令式编程风格的同时,也支持函数式编程风格。因此,你可以使 用最熟悉的风格立即开始编程,而不用承受陡峭的学习曲线。
3.1 Scala:简洁的 Java
FromJavaToScala/Greetings.java
//Java code
public class Greetings {
public static void main(String[] args) {
for(int i = 1; i < 4; i++) {
System.out.print(i + ",");
}
System.out.println("Scala Rocks!!!");
}
}
运行结果
1,2,3,Scala Rocks!!!
FromJavaToScala/Greet.scala
for (i <- 1 to 3) {
print(s"$i,")
}
println("Scala Rocks!!!")
运行结果
FromJavaToScala/Greet.scala
1,2,3,Scala Rocks!!!
FromJavaToScala/GreetExclusiveUpper.scala
for (i <- 1 until 3) {
print(s"$i,")
}
println("Scala Rocks!!!")
运行结果
1,2,Scala Rocks!!!
FromJavaToScala/GreetForEach.scala
(1 to 3).foreach(i => print(s"$i,"))
println("Scala Rocks!!!")
运行结果
1,2,3,Scala Rocks!!!
3.2 Java 原始类型对应的 Scala 类
FromJavaToScala/ScalaInt.scala
class ScalaInt {
def playWithInt(): Unit = {
val capacity: Int = 10
val list = new java.util.ArrayList[String]
list.ensureCapacity(capacity)
}
}
3.3 元组和多重赋值
FromJavaToScala/MultipleAssignment.scala
def getPersonInfo(primaryKey: Int) = {
// Assume primaryKey is used to fetch a person's info...
// Here response is hard-coded
("Venkat", "Subramaniam", "venkats@agiledeveloper.com")
}
val (firstName, lastName, emailAddress) = getPersonInfo(1)
println(s"First Name: $firstName")
println(s"Last Name: $lastName")
println(s"Email Address: $emailAddress")
运行结果
First Name: Venkat
Last Name: Subramaniam
Email Address: venkats@agiledeveloper.com
FromJavaToScala/MultipleAssignment2.scala
def getPersonInfo(primaryKey: Int): (String, String, String) = {
("Venkat", "Subramaniam", "venkats@agiledeveloper.com")
}
val (firstName, lastName) = getPersonInfo(1)
运行结果
MultipleAssignment2.scala:5: error: constructor cannot be instantiated to
expected type;
found : (T1, T2)
required: (String, String, String)
val (firstName, lastName) = getPersonInfo(1)
^
one error found
3.4 灵活的参数和参数值
FromJavaToScala/Parameters.scala
def max(values: Int*) = values.foldLeft(values(0)) { Math.max }
FromJavaToScala/Parameters.scala
max(8, 2, 3)
FromJavaToScala/Parameters.scala
max(2, 5, 3, 7, 1, 6)
FromJavaToScala/ArgType.scala
def function(input: Int*): Unit = println(input.getClass)
function(1, 2, 3)
运行结果
class scala.collection.mutable.WrappedArray$ofInt
FromJavaToScala/CantSendArray.scala
val numbers = Array(2, 5, 3, 7, 1, 6)
max(numbers) // type mismatch error
运行结果
CantSendArray.scala:5: error: type mismatch;
found : Array[Int]
required: Int
max(numbers) // type mismatch error
^
one error found
FromJavaToScala/Parameters.scala
val numbers = Array(2, 5, 3, 7, 1, 6)
max(numbers: _*)
FromJavaToScala/DefaultValues.scala
def mail(destination: String = "head office", mailClass: String = "first"): Unit =
println(s"sending to $destination by $mailClass class")
FromJavaToScala/DefaultValues.scala
mail("Houston office", "Priority")
mail("Boston office")
mail()
运行结果
sending to Houston office by Priority class
sending to Boston office by first class
sending to head office by first class
FromJavaToScala/Named.scala
mail(mailClass = "Priority", destination = "Bahamas office")
FromJavaToScala/Named.scala
mail(mailClass = "Priority")
3.5 隐式参数
FromJavaToScala/ImplicitParameters.scala
class Wifi(name: String) {
override def toString: String = name
}
def connectToNetwork(user: String)(implicit wifi: Wifi): Unit = {
println(s"User: $user connected to WIFI $wifi")
}
def atOffice(): Unit = {
println("--- at the office ---")
implicit def officeNetwork: Wifi = new Wifi("office-network")
val cafeteriaNetwork = new Wifi("cafe-connect")
connectToNetwork("guest")(cafeteriaNetwork)
connectToNetwork("Jill Coder")
connectToNetwork("Joe Hacker")
}
def atJoesHome(): Unit = {
println("--- at Joe's home ---")
implicit def homeNetwork: Wifi = new Wifi("home-network")
connectToNetwork("guest")(homeNetwork)
connectToNetwork("Joe Hacker")
}
atOffice()
atJoesHome()
运行结果
--- at the office ---
User: guest connected to WIFI cafe-connect
User: Jill Coder connected to WIFI office-network
User: Joe Hacker connected to WIFI office-network
--- at Joe's home ---
User: guest connected to WIFI home-network
User: Joe Hacker connected to WIFI home-network
3.6 字符串和多行原始字符串
FromJavaToScala/MultiLine.scala
val str = """In his famous inaugural speech, John F. Kennedy said
"And so, my fellow Americans: ask not what your country can do
for you-ask what you can do for your country." He then proceeded
to speak to the citizens of the World..."""
println(str)
运行结果
In his famous inaugural speech, John F. Kennedy said
"And so, my fellow Americans: ask not what your country can do
for you-ask what you can do for your country." He then proceeded
to speak to the citizens of the World...
FromJavaToScala/MultiLine2.scala
val str = """In his famous inaugural speech, John F. Kennedy said
|"And so, my fellow Americans: ask not what your country can do
|for you-ask what you can do for your country." He then proceeded
|to speak to the citizens of the World...""".stripMargin
println(str)
运行结果
In his famous inaugural speech, John F. Kennedy said
"And so, my fellow Americans: ask not what your country can do
for you-ask what you can do for your country." He then proceeded
to speak to the citizens of the World...
FromJavaToScala/StringInterpolation.scala
val message = s"A discount of $discount% has been applied"
FromJavaToScala/StringInterpolation.scala
var price = 90
val totalPrice = s"The amount of discount is ${price * discount / 100} dollars"
FromJavaToScala/StringInterpolation.scala
val totalPrice = s"The amount of discount is $$${price * discount / 100}"
FromJavaToScala/StringInterpolation.scala
val discount = 10
var price = 100
val totalPrice =
s"The amount after discount is $$${price * (1 - discount / 100.0)}"
println(totalPrice)
price = 50
println(totalPrice)
运行结果
The amount after discount is $90.0
The amount after discount is $90.0
FromJavaToScala/StringInterpolation.scala
val product = "ticket"
val price = 25.12
val discount = 10
println(s"On $product $discount% saves $$${price * discount / 100.00}")
运行结果
On ticket 10% saves $2.512
3.9 操作符重载
FromJavaToScala/Complex.scala
class Complex(val real: Int, val imaginary: Int) {
def +(operand: Complex): Complex = {
new Complex(real + operand.real, imaginary + operand.imaginary)
}
override def toString: String = {
val sign = if (imaginary < 0) "" else "+"
s"$real$sign${imaginary}i"
}
}
val c1 = new Complex(1, 2)
val c2 = new Complex(2, -3)
val sum = c1 + c2
println(s"($c1) + ($c2) = $sum")
运行结果
(1+2i) + (2-3i) = 3-1i
FromJavaToScala/Complex2.scala
class Complex(val real: Int, val imaginary: Int) {
def +(operand: Complex): Complex = {
println("Calling +")
new Complex(real + operand.real, imaginary + operand.imaginary)
}
def *(operand: Complex): Complex = {
println("Calling *")
new Complex(
real * operand.real - imaginary * operand.imaginary,
real * operand.imaginary + imaginary * operand.real)
}
override def toString: String = {
val sign = if (imaginary < 0) "" else "+"
s"$real$sign${imaginary}i"
}
}
val c1 = new Complex(1, 4)
val c2 = new Complex(2, -3)
val c3 = new Complex(2, 2)
println(c1 + c2 * c3)
运行结果
Calling *
Calling +
11+2i
3.10 Scala 与 Java 的差异
FromJavaToScala/SerialAssignments.scala
var a = 1
var b = 2
a = b = 3 //Error
运行结果
SerialAssignments.scala:4: error: type mismatch;
found : Unit
required: Int
a = b = 3
^
one error found
FromJavaToScala/Equality.scala
val str1 = "hello"
val str2 = "hello"
val str3 = new String("hello")
println(str1 == str2) // Equivalent to Java's str1.equals(str2)
println(str1 eq str2) // Equivalent to Java's str1 == str2
println(str1 == str3)
println(str1 eq str3)
运行结果
true
true
true
false
FromJavaToScala/OptionalSemicolon.scala
val list1 = new java.util.ArrayList[Int];
{
println("Created list1")
}
val list2 = new java.util.ArrayList[Int] {
println("Created list2")
}
println(list1.getClass)
println(list2.getClass)
运行结果
Created list1
Created list2
class java.util.ArrayList
class Main$$anon$2$$anon$1
FromJavaToScala/AvoidExplicitReturn.scala
def check1 = true
def check2: Boolean = return true
def check3: Boolean = true
println(check1)
println(check2)
println(check3)
运行结果
true
true
true
3.11 默认访问修饰符
FromJavaToScala/Access.scala
class Microwave {
def start(): Unit = println("started")
def stop(): Unit = println("stopped")
private def turnTable(): Unit = println("turning table")
}
val microwave = new Microwave
microwave.start() // OK
运行结果
Access.scala:9: error: method turnTable in class Microwave cannot be
accessed in this.Microwave
microwave.turnTable() //ERROR
^
one error found
FromJavaToScala/Protected.scala
class Vehicle {
protected def checkEngine() {}
}
class Car extends Vehicle {
def start() { checkEngine() /*OK*/ }
def tow(car: Car) {
car.checkEngine() //OK
}
def tow(vehicle: Vehicle) {
vehicle.checkEngine() //ERROR
}
}
class GasStation {
def fillGas(vehicle: Vehicle) {
vehicle.checkEngine() //ERROR
}
}
运行结果
Protected.scala:12: error: method checkEngine in class Vehicle cannot be
accessed in automobiles.Vehicle
Access to protected method checkEngine not permitted because
prefix type automobiles.Vehicle does not conform to
class Car in package automobiles where the access take place
vehicle.checkEngine() //ERROR
^
Protected.scala:17: error: method checkEngine in class Vehicle cannot be
accessed in automobiles.Vehicle
Access to protected method checkEngine not permitted because
enclosing class GasStation in package automobiles is not a subclass of
class Vehicle in package automobiles where target is defined
vehicle.checkEngine() //ERROR
^
two errors found
FromJavaToScala/FineGrainedAccessControl.scala
package society {
package professional {
class Executive {
private[professional] var workDetails = null
private[society] var friends = null
private[this] var secrets = null
def help(another: Executive): Unit = {
println(another.workDetails)
println(secrets)
println(another.secrets) //ERROR
}
}
class Assistant {
def assist(anExec: Executive): Unit = {
println(anExec.workDetails)
println(anExec.friends)
}
}
}
package social {
class Acquaintance {
def socialize(person: professional.Executive) {
println(person.friends)
println(person.workDetails) // ERROR
}
}
}
}
运行结果
FineGrainedAccessControl.scala:12: error: value secrets is not a member of
society.professional.Executive
println(another.secrets) //ERROR
^
FineGrainedAccessControl.scala:28: error: variable workDetails in class
Executive cannot be accessed in society.professional.Executive
println(person.workDetails) // ERROR
^
two errors found