从 Java 访问 Scala 嵌套类
Posted
技术标签:
【中文标题】从 Java 访问 Scala 嵌套类【英文标题】:Accessing Scala nested classes from Java 【发布时间】:2015-08-28 19:37:45 【问题描述】:假设我们在 Scala 中有以下类结构。
object Foo
class Bar
我们可以使用new Foo.Bar()
在Java 中轻松构造Bar
。但是当我们添加一层额外的嵌套类时,一切都会改变。
object Foo
object Bar
class Baz
不知何故,再也不可能在 Java 中构造最内部的类Baz
。查看javap
输出,我看不出第一种情况(2 个级别)和第二种情况(3 个级别)之间有任何显着差异。生成的代码对我来说看起来很合理。
2 级:
public class Foo$Bar ...
3 级
public class Foo$Bar$Baz ...
话虽如此,从 Java 访问时,2 级和 3 级嵌套的 Scala 类之间有什么区别?
【问题讨论】:
【参考方案1】:让我们给这两个版本起不同的名字,让他们更容易谈论:
object Foo1
class Bar1
object Foo2
object Bar2
class Baz2
现在,如果您查看类文件,您会看到 Scala 编译器创建了一个 Foo1
类。当您在 Foo1$Bar1
上运行 javap -v
时,您会看到该类被列为封闭类:
InnerClasses:
public static #14= #2 of #13; //Bar1=class Foo1$Bar1 of class Foo1
这正是 Java 中静态嵌套类会发生的情况,因此 Java 编译器非常乐意为您编译 new Foo1.Bar1()
。
现在查看javap -v
的Foo2$Bar2$Baz2
输出:
InnerClasses:
public static #16= #13 of #15; //Bar2$=class Foo2$Bar2$ of class Foo2
public static #17= #2 of #13; //Baz2=class Foo2$Bar2$Baz2 of class Foo2$Bar2$
现在封闭类是Foo2$Bar2$
,而不是Foo2$Bar2
(实际上Scala 编译器甚至不会生成Foo2$Bar2
,除非您为object Bar2
添加一个伴随类)。 Java 编译器期望封闭类Foo2$Bar2$
的静态内部类Baz2
命名为Foo2$Bar2$$Baz2
,并带有两个美元符号。这与实际得到的 (Foo2$Bar2$Baz2
) 不符,因此它拒绝 new Foo2.Bar2.Baz2()
。
Java 非常乐意接受类名中的美元符号,在这种情况下,由于它无法弄清楚如何将 Foo2$Bar2$Baz2
解释为某种内部类,它会让你创建一个带有 @ 的实例987654340@。所以这是一种解决方法,只是不是很漂亮。
为什么 Scala 编译器对待 Foo1
和 Bar2
不同(从某种意义上说,Bar2
没有得到 Bar2
类),以及为什么 InnerClasses
属性中列出的封闭类Baz2
末尾有一个美元符号,而 Bar1
没有?我真的没有任何想法。但这就是区别——您只需要更详细一点即可通过javap
看到它。
【讨论】:
以上是关于从 Java 访问 Scala 嵌套类的主要内容,如果未能解决你的问题,请参考以下文章