首页 > 解决方案 > Groovy:如何使用类的内部枚举作为类外的参数类型

问题描述

Given 是一个EnumTest声明内部枚举的类MyEnum

在类中使用MyEnum作为参数类型按预期工作。

MyEnum在外部用作参数类型EnumTest无法使用unable to resolve class test.EnumTest.MyEnum.

我浏览了相关问题,其中最好的一个是this,但它们没有解决使用枚举作为类型的具体问题。

我是否在这里遗漏了一些非常明显的东西(因为我对 Groovy 很陌生)?或者这只是该语言关于枚举的另一个怪癖 “增强” ?

编辑:这只是一个演示问题的测试。实际问题发生在 Jenkins JobDSL 中,否则类路径和导入似乎很好。

Groovy Version: 2.4.8
JVM: 1.8.0_201 
Vendor: Oracle Corporation
OS: Linux

$ tree test
test
├── EnumTest.groovy
├── File2.groovy
└── File3.groovy

EnumTest.groovy:

package test

public class EnumTest {
  public static enum MyEnum {
    FOO, BAR 
  }

  def doStuff(MyEnum v) {
    println v
  }
}

文件 2.groovy:

package test

import test.EnumTest 

// prints BAR 
new EnumTest().doStuff(EnumTest.MyEnum.BAR)

// prints FOO 
println EnumTest.MyEnum.FOO

文件 3.groovy:

package test

import test.EnumTest

// fails: unable to resolve class test.EnumTest.MyEnum
def thisShouldWorkIMHO(EnumTest.MyEnum v) {
   println v
}

当我使用 运行测试文件groovy -cp %时,输出如下:

# groovy -cp . File2.groovy
BAR
FOO

# groovy -cp . File3.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/lwille/-/test/GroovyTest2.groovy: 6: unable to resolve class EnumTest.MyEnum 
 @ line 6, column 24.
   def thisShouldWorkIMHO(EnumTest.MyEnum v) {
                          ^

1 error

标签: groovyenums

解决方案


有几点值得一提。您不需要从同一个包中导入类。其次,当您使用包时,test您需要从根文件夹执行 Groovy,例如groovy test/File3.groovy正确设置类路径。(在这种情况下无需使用-cp .)。

这是它应该的样子。

$ tree test 
test
├── EnumTest.groovy
├── File2.groovy
└── File3.groovy

0 directories, 3 files

测试/EnumTest.groovy

package test

public class EnumTest {
    public static enum MyEnum {
        FOO, BAR
    }

    def doStuff(MyEnum v) {
        println v
    }
}

测试/File2.groovy

package test

// prints BAR
new EnumTest().doStuff(EnumTest.MyEnum.BAR)

// prints FOO
println EnumTest.MyEnum.FOO

测试/File3.groovy

package test

// fails: unable to resolve class test.EnumTest.MyEnum
def thisShouldWorkIMHO(EnumTest.MyEnum v) {
    println v
}

thisShouldWorkIMHO(EnumTest.MyEnum.BAR)

控制台输出:

$ groovy test/File2.groovy 
BAR
FOO

$ groovy test/File3.groovy
BAR

但是,如果要从test文件夹内执行脚本,则需要指定类路径以指向父文件夹,例如:

$ groovy -cp ../. File3.groovy
BAR

$ groovy -cp . File3.groovy   
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/wololock/workspace/groovy-sandbox/src/test/File3.groovy: 4: unable to resolve class EnumTest.MyEnum 
 @ line 4, column 24.
   def thisShouldWorkIMHO(EnumTest.MyEnum v) {
                          ^

1 error

更新:Groovy 2.4 和 2.5 版本之间的区别

值得一提的是——上述解决方案适用于 Groovy 2.5.x及更高版本。重要的是要了解方法参数类型检查等事情发生在编译器Phase.SEMANTIC_ANALYSIS阶段。在 Groovy 2.4 版本中,语义分析类解析发生在不加载类的情况下。在使用内部类的情况下,加载其外部类以便解决问题至关重要。Groovy 2.5 解决了这个问题(有意或无意),语义分析解决了内部类,而没有在这个问题中提到的问题。

有关更详细的分析,请检查以下 Stack Overflow 问题GroovyScriptEngine throws MultipleCompilationErrorsException while loading class that uses other class' static internal class我调查了在 Groovy 2.4 脚本中发现的类似问题。我在那里一步一步地解释了如何挖掘这个问题的根源。


推荐阅读