FunTester Groovy 枚举类初始化异常

FunTester · 2021年01月05日 · 1004 次阅读

之前写过一些Groovy 重载操作符(终极版)的文章,中间用了内部的枚举类,然后通过一个static HPS getInstance(char c)方法获取不同的枚举对象,今天想着把中间的字符去掉,放在枚举类属性中。却发现了一个错误,又是一顿操作猛如虎,重启缓存二百五。

经过多方求证失败后,我开始还原代码,一点点点排查,终于找到了问题的症结所在。下面分享一下这个坑。

错误的代码

package com.fun.ztest.groovy


import com.fun.moco.MocoServer

class MocoDemo extends MocoServer {


    public static void main(String[] args) {
       println FunTester.FUN

    }


    static enum FunTester {

        FUN('3'),TESTER('2')

        char name

        FunTester(char name) {
            this.name = name
        }
    }
}

然后运行,控制台输出:

INFO-> 当前用户:fv,IP:10.60.131.54,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
Exception in thread "main" java.lang.ExceptionInInitializerError
    at sun.misc.Unsafe.ensureClassInitialized(Native Method)
    at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
    at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:142)
    at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1088)
    at java.lang.reflect.Field.getFieldAccessor(Field.java:1069)
    at java.lang.reflect.Field.get(Field.java:393)
    at org.codehaus.groovy.reflection.CachedField.getProperty(CachedField.java:55)
    at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1804)
    at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3797)
    at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.getProperty(ClassMetaClassGetPropertySite.java:50)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:298)
    at com.fun.ztest.groovy.MocoDemo.main(MocoDemo.groovy:10)
Caused by: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.fun.ztest.groovy.MocoDemo$FunTester(String, Integer, String)
    at groovy.lang.MetaClassImpl.createCachedConstructor(MetaClassImpl.java:1613)
    at groovy.lang.MetaClassImpl.selectConstructorAndTransformArguments1(MetaClassImpl.java:1639)
    at groovy.lang.MetaClassImpl.selectConstructorAndTransformArguments(MetaClassImpl.java:1561)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.selectConstructorAndTransformArguments(ScriptBytecodeAdapter.java:250)
    at com.fun.ztest.groovy.MocoDemo$FunTester.$INIT(MocoDemo.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:44)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:100)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:196)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:224)
    at com.fun.ztest.groovy.MocoDemo$FunTester.<clinit>(MocoDemo.groovy)
    ... 12 more

Process finished with exit code 1

乍一看,都是什么神仙错误,居然是初始化异常,而且重点是异常信息Could not find matching constructor for: com.fun.ztest.groovy.MocoDemo$FunTester(String, Integer, String),我始终无法想清楚我在哪里用了这个构造方法。

原因剖析

经过一点点点还原代码,终于发现是添加枚举对象的时候报错的,再一想,Groovy里面对于双引号""和单引号‘’是不区分charString的,应该是这个原因导致枚举类初始化不成功。

使用双引号""和单引号‘’的字符或者字符串对于Groovy都是String类型的对象。

public static void main(String[] args) {
    println "3".class.getName()
    println '3'.class.getName()
}

控制台输出:

INFO-> 当前用户:fv,IP:10.60.131.54,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
java.lang.String
java.lang.String

Process finished with exit code 0

改正

所以在写枚举类对象的时候,需要特殊处理一下字符或者字符串,正确的使用方法如下:

class MocoDemo extends MocoServer {


    public static void main(String[] args) {
       println FunTester.FUN

    }


    static enum FunTester {

        FUN((char)'3'),TESTER((char)'2')

        char name

        FunTester(char name) {
            this.name = name
        }
    }
}

控制台输出

INFO-> 当前用户:fv,IP:10.60.131.54,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
FUN

Process finished with exit code 0


FunTester,非著名测试开发,文章记录学习和感悟,欢迎关注,交流成长。

FunTester 热文精选

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册