前一篇在提到获取Class时的两个方法:classOf 和 getClass
scala> class A
scala> val a = new A
scala> a.getClass
res2: Class[_ <: A] = class A
scala> classOf[A]
res3: Class[A] = class A
上面显示了两者的不同,getClass
方法得到的是 Class[A]的某个子类,而 classOf[A]
得到是正确的 Class[A]
,但是去比较的话,这两个类型是equals为true的
scala> a.getClass == classOf[A]
res13: Boolean = true
这种细微的差别,体现在类型赋值时,因为java里的 Class[T]
是不支持协变的,所以无法把一个 Class[_ < : A]
赋值给一个 Class[A]
scala> val c:Class[A] = a.getClass
<console>:9: error: type mismatch;
协变 逆协变 不协变这些概念有点晕晕的…
原来写过一段笔记不知道对不对…
有一段被过滤掉了….
若 C[A]<:C[B] C 是 covariant
若 C[A]>:C[B] C 是 cotravariant
scala> a.getClass == classOf[A]
res13: Boolean = true
2.11版本已经是false
你确定?你的小版本号是什么?我机器上是2.11.0-RC4 刚测试了一下还是true.
我在2.11.1上测试了,还是true,没有变。
2.11.4 测 试是false
scala> a.getClass == classOf[A]
res18: Boolean = false
前面版本写错了
[hadoop@slave1 ~]$ scala
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
但是在下面版本下
C:\Documents and Settings\Administrator>scala
Welcome to Scala version 2.11.0-M4 (Java HotSpot(TM) Client VM, Java 1.8.0_20).
scala> a.getClass == classOf[A]
res2: Boolean = true
你能把完整的scala版本jdk版本信息 以及执行过程 贴出来吗?我特意下载了一个 2.11.0 的,在 jdk7下运行,也是true
% export JAVA_HOME=”/System/Library/Frameworks/JavaVM.framework/Versions/jdk1.7/Home” && ./scala
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_67).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class A
defined class A
scala> val a = new A
a: A = A@c3cec2e
scala> a.getClass == classOf[A]
res0: Boolean = true
2.11.4 测试,也是 true
2.11.8,windows下测试是false
这个问题很蹊跷,不太可能这种低级bug在编译器反复出现,能否在repl下把重现的步骤给出来。
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102)
scala> class A
defined class A
scala> val a = new A
a: A = A@6f7923a5
scala> a.getClass == classOf[A]
res3: Boolean = true
这就是Windows下的
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102).
Type in expressions for evaluation. Or try :help.
win7 64位
a.getClass == classOf[A]
该版本是false
所有所 a.getClass == classOf[A] 为 false 的能否把完整的代码片段贴出来,我怀疑是你们自己的错误,所有反馈说false的没有一个人给出完整的验证过程。
就像我下面在最新的2.12.1版本里完整的验证过程:
/data/tools/scala-binary/scala-2.12.1/bin [14:41:16]
➜ ./scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_51).
Type in expressions for evaluation. Or try :help.
scala> class A
defined class A
scala> val a = new A
a: A = A@1a3e5f23
scala> a.getClass == classOf[A]
res0: Boolean = true
如果你用的版本得到的是 false ,请贴出完整的过程,避免是你自己的失误。
Welcome to Scala version 2.11.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_121).
一个版本下结果不一致 : 这个是“true”
Welcome to Scala version 2.11.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_121).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class A
defined class A
scala> val a = new A
a: A = A@244038d0
scala> a.getClass == classOf[A]
res0: Boolean = true
scala> a.getClass
res1: Class[_ classOf[A]
res2: Class[A] = class A
scala>
———————————————————————————————————————————-
这个是“false“
scala> val a2 = new A
a2: A = A@7197b07f
scala> val b1 = new a1.B
b1: a1.B = A$B@18709cb2
scala> val b2 = new a2.B
b2: a2.B = A$B@b768a65
scala> b1.getClass
res13: Class[_ b2.getClass
res14: Class[_ typeOf[a1.B]
res15: reflect.runtime.universe.Type = a1.B
scala> typeOf[a2.B]
res16: reflect.runtime.universe.Type = a2.B
scala> typeOf[a1.B]<: typeOf[a1.B]<: classOf[List[Int]] == classOf[List[String]]
res19: Boolean = true
scala> a.getClass == classOf[A]
res20: Boolean = false
scala> a
res21: A = A@29eda4f8
scala> a.getClass
res22: Class[_ classOf[A]
res23: Class[A] = class A
第二段,你把 A 这个class怎么定义的,以及 a 这个值怎么创建的过程也贴出来。
Linux dell 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
系统
还有一点要补充下:
比较不同的代码是
安装你的文章从类型系统第一篇开始模拟的。
比较相同的代码是:
新开了一天终端,直接输入这几个语句。
不同时的反编译:javap A
:javap A
Size 518 bytes
MD5 checksum 00665e3dcb5ab63ad1b690934dcf755b
Compiled from “”
public class A
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 A
#2 = Class #1 // A
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8
#6 = Utf8
#7 = Utf8 ()V
#8 = NameAndType #6:#7 // “”:()V
#9 = Methodref #4.#8 // java/lang/Object.””:()V
#10 = Utf8 this
#11 = Utf8 LA;
#12 = Utf8
#13 = Class #12 //
#14 = Utf8 $line30/$read
#15 = Class #14 // $line30/$read
#16 = Utf8
#17 = Utf8
#18 = Class #17 //
#19 = Utf8
#20 = Class #19 //
#21 = Utf8
#22 = Class #21 //
#23 = Utf8 A
#24 = Utf8 Code
#25 = Utf8 LocalVariableTable
#26 = Utf8 LineNumberTable
#27 = Utf8 SourceFile
#28 = Utf8 InnerClasses
#29 = Utf8 Scala
{
public A();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #9 // Method java/lang/Object.””:()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LA;
LineNumberTable:
line 14: 0
}
SourceFile: “”
InnerClasses:
public static #16= #13 of #15; //=class of class $line30/$read
public static #16= #18 of #13; //=class of class
public static #16= #20 of #18; //=class of class
public static #16= #22 of #20; //=class of class
public static #23= #2 of #22; //A=class A of class
Error: unknown attribute
Scala: length = 0x0
相同时:
scala> :javap A
Size 413 bytes
MD5 checksum 280934bc1bdc79baba079ad87dfd3620
Compiled from “”
public class A
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 A
#2 = Class #1 // A
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8
#6 = Utf8
#7 = Utf8 ()V
#8 = NameAndType #6:#7 // “”:()V
#9 = Methodref #4.#8 // java/lang/Object.””:()V
#10 = Utf8 this
#11 = Utf8 LA;
#12 = Utf8
#13 = Class #12 //
#14 = Utf8 $line3/$read
#15 = Class #14 // $line3/$read
#16 = Utf8
#17 = Utf8
#18 = Class #17 //
#19 = Utf8 A
#20 = Utf8 Code
#21 = Utf8 LocalVariableTable
#22 = Utf8 LineNumberTable
#23 = Utf8 SourceFile
#24 = Utf8 InnerClasses
#25 = Utf8 Scala
{
public A();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #9 // Method java/lang/Object.””:()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LA;
LineNumberTable:
line 11: 0
}
SourceFile: “”
InnerClasses:
public static #16= #13 of #15; //=class of class $line3/$read
public static #16= #18 of #13; //=class of class
public static #19= #2 of #18; //A=class A of class
Error: unknown attribute
Scala: length = 0x0
不需要贴出这些反编译的内容,你只需要把 a.getClass == classOf[A] 返回 false 的那个过程,完整的给贴出来我就知道怎么回事了,你现在贴出来的信息是从中间开始的,我不知道你之前的 A 怎么定义,a怎么创建的。
这个问题可以重现:
进入scala ,从上一篇文章例子输入,不要关闭,到这一篇文章例子中。比较时就会产生不同。
新打开一个终端,安装本篇文章的示例,比较会相同。
我知道了,你开始显示定义了一个 A 且包含内部 B 的class,并创建了一个a的实例
scala> class A { class B }
defined class A
scala> val a = new A
a: A = A@73a28541
你后来又重新定义了一个 A
scala> class A
defined class A
注意,这个时候在REPL下 A 已经覆盖了之前定义的那个 A
所以 比较时返回false
scala> a.getClass == classOf[A]
res3: Boolean = false
是因为这里的 a.getClass 这个值是之前的 class A { class B } 那个被覆盖掉的 A,而 classOf[A] 是新定义的 A
是在 REPL 下同名污染所致
scala> % greister@dell tmp % scala
Welcome to Scala version 2.11.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_121).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> class A
defined class A
scala> typeOf[A]
res0: reflect.runtime.universe.Type = A
scala> classOf[A]
res1: Class[A] = class A
scala> val a = new A
a: A = A@5b970f7
scala> a.getClass
res2: Class[_ a.getClass = classOf[A]
:12: error: reassignment to val
a.getClass = classOf[A]
^
scala> a.getClass == classOf[A]
res3: Boolean = true
scala> class A { class B }
defined class A
scala> val a1 = new A
a1: A = A@1fd386c3
scala> val a2 = new A
a2: A = A@aed0151
scala> val b1 = new a1.B
b1: a1.B = A$B@71178a52
scala> val b2 = new a2.B
b2: a2.B = A$B@543e593
scala> b1.getClass
res4: Class[_ a.getClass == classOf[A]
res5: Boolean = false
你先定义的 Class A 被后来的 Class A { class B} 同名类覆盖掉了。
每次练习前,请先退出一下 REPL ,避免之前同名的类或变量混淆
上个是错误的。
a的值没有变化。
谢谢。上面的朋友出现这个问题,可能都是这个原因。