Groovy:如何使用类的内部枚举作为类外的参数类型

Groovy:如何使用类的内部枚举作为类外的参数类型,groovy,enums,Groovy,Enums,给定的是一个类EnumTest,它声明了一个内部enumMyEnum 在类中使用MyEnum作为参数类型,效果与预期一样 使用MyEnum作为EnumTest之外的参数类型无法编译,无法解析类test.EnumTest.MyEnum 我浏览了相关的问题,其中最好的一个是,但它们没有解决使用枚举作为类型的具体问题 我是否错过了一些非常明显的东西(因为我是Groovy的新手)?或者这只是该语言关于枚举的另一个怪癖“增强” 编辑:这只是一个演示问题的测试。实际的问题发生在Jenkins JobDSL中

给定的是一个类
EnumTest
,它声明了一个内部enum
MyEnum

在类中使用
MyEnum
作为参数类型,效果与预期一样

使用
MyEnum
作为
EnumTest
之外的参数类型无法编译,无法解析类test.EnumTest.MyEnum

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

我是否错过了一些非常明显的东西(因为我是Groovy的新手)?或者这只是该语言关于枚举的另一个怪癖“增强”

编辑:这只是一个演示问题的测试。实际的问题发生在Jenkins JobDSL中,而类路径和导入在其他方面似乎没有问题

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

EnumTest.groovy:

package test

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

  def doStuff(MyEnum v) {
    println v
  }
}
File2.groovy:

package test

import test.EnumTest 

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

// prints FOO 
println EnumTest.MyEnum.FOO
File3.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

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

下面是它应该是什么样子

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

0 directories, 3 files
test/EnumTest.groovy

test/File2.groovy

test/File3.groovy

控制台输出:

$ 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版本之间的差异 值得一提的是,上述解决方案适用于Groovy2.5.x及以上版本。理解诸如方法参数类型检查之类的事情发生在编译器的
阶段。语义分析
阶段是很重要的。在Groovy 2.4版本中,语义分析类解析在不加载类的情况下进行。在使用内部类的情况下,加载其外部类以解决问题是至关重要的。Groovy 2.5修复了这个问题(有意或无意),语义分析解决了内部类,而没有在这个问题中提到的问题


要获得更详细的分析,请检查下面的堆栈溢出问题,我在这里调查了Groovy 2.4脚本中发现的类似问题。我在那里一步一步地解释了如何找到这个问题的根源。

谢谢你的回答!如果是我的环境造成的,为什么文件2可以工作?这只是一个证明问题的测试。实际的问题发生在Jenkins JobDSL中,而类路径和导入在其他方面似乎没有问题。现在我测试了建议的更改,无论我是否设置类路径或跳过导入类,它都不会改变任何东西。我的Groovy版本是2.4.8,你的版本是什么?我使用了Groovy 2.5.6,我可以确认在任何Groovy 2.4.x版本中都存在这个问题(我检查了2.4.8以及最新的2.4.16)。你的问题听起来和我差不多一年前调查的问题很相似()。长故事短方法参数类型在编译器的
阶段.语义分析
阶段解析。这里的问题是(至少在Groovy 2.4中)这个编译阶段不加载类,任何内部类都需要加载外部类才能解决。Groovy2.5解决了这个问题(不管是有意还是无意)。请把它写下来作为答案,我会接受的。谢谢你的支持!完成。谢谢!
package test

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

// prints FOO
println EnumTest.MyEnum.FOO
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
$ 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