解释下面代码的运行结果
Scala
package sparksessiondemo
object adress {
def main(args: Array[String]): Unit = {
val a:Integer = 10
val b:Integer = 10
println(a == b) //true
println(a.equals(b)) //true
println(a.eq(b)) //true
val a1: Integer = 128
val b1: Integer = 128
println(a1 == b1) //true
println(a1.equals(b1)) //true
println(a1.eq(b1)) //false
val c: Int = 10
val d: Int = 10
println(c == d) //true
println(c.equals(d)) //true
//println(c.eq(d)) //the result type of an implicit conversion must be more specific than AnyRef
val c1: Int = 128
val d1: Int = 128
println(c1 == d1) //true
println(c1.equals(d1)) //true
// println(c1.eq(d1)) //the result type of an implicit conversion must be more specific than AnyRef
val e: String = "128"
val f: String = "128"
println(e == f) //true
println(e.equals(f)) //true
println(e.eq(f)) //true
val e1: String = new String("128")
val f1: String = new String("128")
println(e1 == f1) //true
println(e1.equals(f1)) //true
println(e1.eq(f1)) //false
}
}
这段代码展示了 Scala 中不同类型(Integer
、Int
和 String
)的比较操作,涉及 ==
、equals
和 eq
三种比较方式。以下是对代码结果的详细解释:
1. Integer
类型的比较
Integer
是 Java 中的包装类,Scala 继承了 Java 的行为。
第一部分:a
和 b
的比较
Scala
val a: Integer = 10
val b: Integer = 10
println(a == b) // true
println(a.equals(b)) // true
println(a.eq(b)) // true
-
a == b
:==
是值比较,10 == 10
,结果为true
。
-
a.equals(b)
:equals
是值比较,10.equals(10)
,结果为true
。
-
a.eq(b)
:eq
是引用比较。由于10
在-128
到127
范围内,a
和b
指向缓存中的同一个对象,结果为true
。
第二部分:a1
和 b1
的比较
Scala
val a1: Integer = 128
val b1: Integer = 128
println(a1 == b1) // true
println(a1.equals(b1)) // true
println(a1.eq(b1)) // false
-
a1 == b1
:- 值比较,
128 == 128
,结果为true
。
- 值比较,
-
a1.equals(b1)
:- 值比较,
128.equals(128)
,结果为true
。
- 值比较,
-
a1.eq(b1)
:- 引用比较。由于
128
超出了-128
到127
的范围,a1
和b1
是两个不同的对象,结果为false
。
- 引用比较。由于
2. Int
类型的比较
Int
是 Scala 中的基本类型(值类型),不是引用类型。
第一部分:c
和 d
的比较
Scala
val c: Int = 10
val d: Int = 10
println(c == d) // true
println(c.equals(d)) // true
// println(c.eq(d)) // 编译错误
-
c == d
:- 值比较,
10 == 10
,结果为true
。
- 值比较,
-
c.equals(d)
:- 值比较,
10.equals(10)
,结果为true
。
- 值比较,
-
c.eq(d)
:eq
是引用比较,但Int
是值类型,没有引用。Scala 会尝试将Int
隐式转换为AnyRef
,但无法确定具体类型,因此编译错误。
第二部分:c1
和 d1
的比较
Scala
val c1: Int = 128
val d1: Int = 128
println(c1 == d1) // true
println(c1.equals(d1)) // true
// println(c1.eq(d1)) // 编译错误
-
c1 == d1
:- 值比较,
128 == 128
,结果为true
。
- 值比较,
-
c1.equals(d1)
:- 值比较,
128.equals(128)
,结果为true
。
- 值比较,
-
c1.eq(d1)
:- 同上,
Int
是值类型,无法进行引用比较,编译错误。
- 同上,
3. String
类型的比较
String
是引用类型,Scala 中的 String
行为与 Java 一致。
第一部分:e
和 f
的比较
Scala
val e: String = "128"
val f: String = "128"
println(e == f) // true
println(e.equals(f)) // true
println(e.eq(f)) // true
-
e == f
:- 值比较,
"128" == "128"
,结果为true
。
- 值比较,
-
e.equals(f)
:- 值比较,
"128".equals("128")
,结果为true
。
- 值比较,
-
e.eq(f)
:- 引用比较。由于字符串常量池的存在,
e
和f
指向同一个对象,结果为true
。
- 引用比较。由于字符串常量池的存在,
第二部分:e1
和 f1
的比较
Scala
val e1: String = new String("128")
val f1: String = new String("128")
println(e1 == f1) // true
println(e1.equals(f1)) // true
println(e1.eq(f1)) // false
-
e1 == f1
:- 值比较,
"128" == "128"
,结果为true
。
- 值比较,
-
e1.equals(f1)
:- 值比较,
"128".equals("128")
,结果为true
。
- 值比较,
-
e1.eq(f1)
:- 引用比较。由于
new String("128")
创建了新的对象,e1
和f1
是两个不同的对象,结果为false
。
- 引用比较。由于
总结
类型 | 操作符/方法 | 比较内容 | 结果(值 10 或 "128") | 结果(值 128 或 new String("128")) |
---|---|---|---|---|
Integer |
== |
值比较 | true |
true |
equals |
值比较 | true |
true |
|
eq |
引用比较 | true (缓存) |
false (新对象) |
|
Int |
== |
值比较 | true |
true |
equals |
值比较 | true |
true |
|
eq |
引用比较 | 编译错误 | 编译错误 | |
String |
== |
值比较 | true |
true |
equals |
值比较 | true |
true |
|
eq |
引用比较 | true (常量池) |
false (新对象) |
关键点
-
Integer
的缓存机制:-
Java 和 Scala 对
Integer
类型有一个缓存机制:对于值在-128
到127
之间的Integer
对象,会从缓存中返回相同的对象,eq
返回true
。 -
对于超出这个范围的值,每次都会创建新的
Integer
对象,eq
返回false
。
-
-
Int
是值类型:Int
没有引用,eq
无法使用。
-
String
的常量池:-
直接赋值的字符串会使用常量池,
eq
返回true
。 -
使用
new String
创建的对象会生成新的引用,eq
返回false。
-
关于String常量池的更详细说明,见:
Scala 中的String常量池-CSDN博客
-
通过这些例子,可以清楚地理解 Scala 中不同类型的行为及其比较操作的区别。