Nae*_*mul 14 primitive scala equality equals
在scaladoc中scala.Any,解释了运算符==(或方法==):
该表达式
x == that相当于if (x eq null) that eq null else x.equals(that)http://www.scala-lang.org/api/current/#scala.Any
对于子类的对象AnyRef,我可以很容易地理解它,我没有看到任何奇怪的东西.
然而,对于值AnyVal,(我的意思是Int,Double,Long,等,)上面的定义是有点棘手(1 eq null?如果我们不转变这并不编译1到java.lang.Integer中).此外,==和equals()不同的表现.
我举几个例子.
scala> 1 == 1 res0: Boolean = true scala> 1 == 1.0 res1: Boolean = true scala> 1 == 1.2 res2: Boolean = false scala> 2 == BigInt(2) res3: Boolean = true scala> 2.0 == BigInt(2) res4: Boolean = true scala> 2 == BigInt(3) res5: Boolean = false
到目前为止,没有什么奇怪的.但如果我们用equals()方法做同样的事情,
scala> 1 equals 1 res7: Boolean = true scala> 1 equals 1.0 res8: Boolean = false scala> 1 equals 1.2 res9: Boolean = false scala> 2 equals BigInt(2) res10: Boolean = false scala> 2.0 equals BigInt(2) res11: Boolean = false scala> 2 equals BigInt(3) res12: Boolean = false
因此,如果类型不同,则equals()始终返回false,而==如果它们转换为相同类型,则表示它们表示相同的值.
在子类的情况下AnyRef,方法==和equals()返回相同.
scala> BigInt(2) == 2 res25: Boolean = true scala> BigInt(2) == 2.0 res26: Boolean = true scala> BigInt(3) == 2 res27: Boolean = false scala> BigInt(2) equals 2 res28: Boolean = true scala> BigInt(2) equals 2.0 res29: Boolean = true scala> BigInt(3) equals 2 res30: Boolean = false
那么,为什么方法==和equals()不同AnyVal?
我正在使用Scala版本2.10.2(Java HotSpot(TM)64位服务器VM,Java 1.7.0_25).
编辑1
我看到==不能直接覆盖,因为它被定义为类Any中的最终方法,根据Scala编程,第2版.
编辑2
虽然有答案,但我的问题仍然存在.我会打开这个问题.与Java
相对应的是Java的原始类型和.
在Java中,并且是类,因此它们的变量是引用,它们可以具有.这意味着,他们就像Scala一样.没有.
Scala的- 并且不能有价值,Java 和Java也不能.
此外,的在Java是引用相等(相同Scala中).
在这方面,您在Scala REPL中使用的内容与使用.java源文件的纯Java项目中的内容完全不同.
但是,我在Java中使用原始类型的类可以得到:(这是JAVA)scala.Intscala.Longintlongjava.lang.Integerjava.lang.LongnullAnyRefAnyValAnyValscala.Intscala.Longnullintlongjava.lang.Integer==eqjava.lang.Integer
class Main {
public static void main(String[] args) {
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1L)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1.0)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Integer(1))));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Long(1))));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
true false false true false是的,它们的行为类似于scala AnyVal
equals().但是,那么,为什么会发生这种情况呢?
请问Scala的AnyVal的==对应==Java的原始类型的
和不Scala的AnyVal的equals()对应于equals()Java的类类型的?
使用BigInt进行相等测试怎么样?Java中没有相应的原始类型.
问题仍然存在......
编辑3
我可以从scaladoc找到一些信息.(http://www.scala-lang.org/api/current/index.html#scala.Int)
的隐含信息从该项目阴影内含价值会员,
我能找到==超载了Char,Short,Float,和... ,
并且==将调用隐式转换int2double,int2float或int2long.
而equals()仅定义为Any,它将调用隐式转换int2Integer.
也就是说,Int.equals()将是一样的java.lang.Integer.equals().
还有一个问题:
为什么==的AnyVal过载,并且equals()的AnyVal不超载?
som*_*ytt 11
相关讨论是描述性的
和投机的
FWIW,规范在12.2中调用数值类型的相等性.
或者,在HTML中.(在下面的底部引用.)
在2010年的"pidgin spec-ese"中,Paul Phillips这样说道:
将两个基元(盒装或未装箱)与==进行比较时,应始终通过将这些值作为未装箱的基元进行比较来给出结果.当你直接调用equals时,你正在跳过所有软化逻辑,而是将java理论视为两个不同类型的盒装值总是不相等的.
该规范没有提到盒装基元,除了在12.5中通过引用提供的转换Predef.您通常不会意识到基元何时以"盒装"形式存储,除非您出于性能原因需要这样做.
因此,例如,这些值会以静默方式取消装箱并为您提升:
scala> val ds = List(7.0)
ds: List[Double] = List(7.0)
scala> val is = List(7)
is: List[Int] = List(7)
scala> ds(0) == is(0)
res24: Boolean = true
scala> :javap -
Size 1181 bytes
MD5 checksum ca732fd4aabb301f3ffe0e466164ed50
Compiled from "<console>"
[snip]
9: getstatic #26 // Field .MODULE$:L;
12: invokevirtual #30 // Method .ds:()Lscala/collection/immutable/List;
15: iconst_0
16: invokevirtual #36 // Method scala/collection/immutable/List.apply:(I)Ljava/lang/Object;
19: invokestatic #42 // Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
22: getstatic #47 // Field .MODULE$:L;
25: invokevirtual #50 // Method .is:()Lscala/collection/immutable/List;
28: iconst_0
29: invokevirtual #36 // Method scala/collection/immutable/List.apply:(I)Ljava/lang/Object;
32: invokestatic #54 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I
35: i2d
36: dcmpl
Run Code Online (Sandbox Code Playgroud)
你注意到我有点惊讶
2.0 == BigInt(2) // So far, nothing is strange.
Run Code Online (Sandbox Code Playgroud)
对我来说,这有点神奇.它BoxesRunTime.equals如Paul Phillips所述.
9: ldc2_w #22 // double 2.0d
12: invokestatic #29 // Method scala/runtime/BoxesRunTime.boxToDouble:(D)Ljava/lang/Double;
15: getstatic #34 // Field scala/package$.MODULE$:Lscala/package$;
18: invokevirtual #38 // Method scala/package$.BigInt:()Lscala/math/BigInt$;
21: iconst_2
22: invokevirtual #44 // Method scala/math/BigInt$.apply:(I)Lscala/math/BigInt;
25: invokestatic #48 // Method scala/runtime/BoxesRunTime.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
Run Code Online (Sandbox Code Playgroud)
这是规范,供参考,在这种形式基本上只承诺做正确的事情:
equals方法测试参数是否为数值类型.如果这是真的,它将执行适合该类型的==操作.也就是说,可以认为数值类型的equals方法定义如下:
def equals(other: Any): Boolean = other match {
case that: Byte => this == that
case that: Short => this == that
case that: Char => this == that
case that: Int => this == that
case that: Long => this == that
case that: Float => this == that
case that: Double => this == that
case _ => false
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8207 次 |
| 最近记录: |