如何在 Java 中传递嵌套的 Scala 对象引用?

How to pass nested scala object reference in Java?

之前已经回答了一些问题。

但我的问题是我有嵌套的 Scala 对象,例如:

object Criteria {
    object ActionCriteria {
        case class Action (parameter: String) {
            def this(parameter: String) = { this(paramerter) }
        }

        object Action {
           def apply(parameter: String): Action = { apply(parameter) }
        } 
    }
}

在 java 然后我需要创建一个动作列表。我已经试过了...无济于事:

import Criteria.ActionCriteria.Action$

....

List<Criteria.ActionCriteria.Action$.MODULE$> actions = new ArrayList<>();

以及许多其他组合,例如为每个对象添加 $.MODULE$。现在我收到以下错误:

error: cannot find symbol Criteria.ActionCriteria
List<Criteria$ActionCriteria$Action> actions = new ArrayList<>();

似乎工作正常。用 Scala REPL 找到这个:

scala> classOf[Criteria.ActionCriteria.Action]
res1: Class[Criteria.ActionCriteria.Action] = class Criteria$ActionCriteria$Action

如果你想要 Action 对象的类型,而不是 class 的大小写(极不可能,但为了完整起见):

scala> Criteria.ActionCriteria.Action.getClass
res2: Class[_ <: Criteria.ActionCriteria.Action.type] = class Criteria$ActionCriteria$Action$

差异是由于 Scala 期望 ActionclassOf[Action] 中的类型,所以它 returns 对应于 class 的类型。当您在需要值的上下文中使用 Action 时,它 returns 是单例实例,因此您可以调用标准 Java 方法 getClass 来获取 object Action.

如果您需要其他类型:

Criteria$                       cm    = Criteria$.MODULE$;
Criteria.ActionCriteria$        cacm  = Criteria.ActionCriteria$.MODULE$;
Criteria$ActionCriteria$Action$ cacam = Criteria$ActionCriteria$Action$.MODULE$;
Criteria$ActionCriteria$Action  caca  = new Criteria$ActionCriteria$Action("Foo");

Criteria.ActionCriteria$ 打破了这里的模式。为什么?根据 Iulian Dragos 在 bug SI-2034 下的评论,这是一个特例:

since objects are "the equivalent of static" in the Java world, we wanted to make it easier for Java code to use static inner classes. When there's only one level of nesting, there's a guaranteed companion: every top-level object gets a mirror class (if there isn't one) that creates static forwarders to module methods (that's how one can run a main method defined inside an object). Therefore, a special case for one-level nesting: those classes use the flattened name (without a $ suffix) as outer_name. So, Java code can say new Outer.Inner.


总结

  • 对于除第一层以外的每一层嵌套,您在 class 名称中将 . 替换为 $

  • 如果目标类型也是对象你在末尾加上$

  • 如果你想要一个实例,你添加 .MODULE$