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

时间:2019-03-29 10:51:39

标签: groovy enums

给定是一个类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
  }
}

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

1 个答案:

答案 0 :(得分:2)

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

这是它的外观。

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

0 directories, 3 files

test / EnumTest.groovy

package test

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

    def doStuff(MyEnum v) {
        println v
    }
}

test / File2.groovy

package test

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

// prints FOO
println EnumTest.MyEnum.FOO

test / 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修复了该问题(有意或无意),并且语义分析解决了内部类,而在此问题中未提及任何问题。

要进行更详细的分析,请检查以下堆栈溢出问题GroovyScriptEngine throws MultipleCompilationErrorsException while loading class that uses other class' static inner class,在该问题中我调查了Groovy 2.4脚本中发现的类似问题。我在那里逐步解释了如何深入探究这个问题的根源。