【问题标题】:Scala can't access Java inner class?Scala 无法访问 Java 内部类?
【发布时间】:2013-10-21 03:59:38
【问题描述】:

我有一个如下所示的 java 类:

public class Constants {
    public class Commands {
        public static final String CreateOrder = "CreateOrder";
    }
}

我想访问“CreateOrder”常量,在java中我可以像这样轻松访问它:

String co = Constants.Commands.CreateOrder

但是在 Scala 中这不起作用,为什么??? 如何从 Scala 访问“CreateOrder”,我无法更改 Java 代码。

谢谢。

【问题讨论】:

  • 你可以试试Constants$Command$CreateOrder 吗?
  • Constants$Command$CreateOrder 不起作用
  • 为什么Commands 是非静态的?
  • 我正在使用其他 java 银行库,但我没有编写 java 代码,无法更改。
  • 这种不兼容性现在困扰着我。有没有人找到反射以外的替代方法?

标签: java scala inner-classes


【解决方案1】:

据我所知,在 Scala 中无法做你想做的事。

但是,如果您绝对无法更改 Java 代码,那么您可以使用一些反射技巧。

val value = classOf[Constants#Commands].getDeclaredField("CreateOrder").get(null)

【讨论】:

  • 我花了几个小时寻找解决这个问题的方法。我正在使用以这种方式定义常量的 3rd 方库。这是唯一有效的方法。 @Travis Brown 下面提出的实例化对象然后访问它的建议对我不起作用。
【解决方案2】:

来自Java Language Specification

内部类不能声明静态成员,除非它们是常量变量(第 4.12.4 节),或者发生编译时错误。

在常量变量的情况下,您可以使用Constants.Commands.CreateOrder 语法,即使通常对Constants.Commands 的任何引用都必须与Constants 的实例相关联,因为它不是静态内部类。

这在 Java 中可以被认为是一种疯狂的一次性语法特殊情况,这是 Scala 语言设计者没有费心将其融入 Scala 的 Java 互操作性的一种东西。

您最好的选择(如果您的真实 Java 类看起来完全像这样)是创建一个 Constants 的实例,此时您可以以非常自然的方式访问内部类的静态字段:

scala> (new Constants).Commands.CreateOrder
res0: String = CreateOrder

如果由于某种原因这不是一个选项,那么不幸的是,您将不得不在另一个答案中使用基于反射的方法。

【讨论】:

    【解决方案3】:

    我认为反射和实例化的第三种替代方法是编写一小段 Java 胶水代码。喜欢

    public class Glue {
        public static String createOrder() { return Constants.Commands.CreateOrder; }
    }
    

    那么在 Scala 中你应该可以写 Glue.createOrder

    【讨论】:

    • 这是我基于反思的答案的一个很好的替代方案。如果您能够/允许向应用程序添加新的 Java 代码,这是一个更好的选择。
    • 附带说明:使用 sbt 构建时,将 .java 文件放入组合中可以开箱即用。在 Java 和 Scala 视角不匹配的极端情况下,这通常是一种快速的工作(我认为可见性是另一种情况)
    猜你喜欢
    • 1970-01-01
    • 2016-03-15
    • 2012-04-17
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多