Keywords: Groovy, Reflection, 反射

The Reflection of Groovy String constant style method.

Groovy支持以下的方法定义:

class A {
def "I am a method"() {
}
}

Groovy是继承Java的机制的,而Java显然是不支持这种函数定义命名的。然而实际上,你是用A.class.getMethods() 或 A.metaClass.getMethods() 都能获取到带空格的方法名,只是调用起来很麻烦,可能只能靠反射去invoke调用。所以一般这种写法主要用于TestSuite做单元测试或测试驱动开发。其实这个反射很简单,难的是下面的。

Spock是个很灵活的Java/Groovy的测试框架(Spock以后有空再介绍),基于JUnit。但是Spock中继承了Specfication的测试类的字符串常量方法,会在groovy compile的时候compile成一个名字类似$spock_feature_0_0 这样的名字,这时候想要找回原来的对应的常量就不是那么简单了。但既然JUnit能做到,我们就去看JUnit的run的源码,发现它会生成一个Sputnik的Runner,这是个Spock的类,其中它会有个private的SpecInfo的字段,里面包含了当前类的所有features。Spock把每个test method看作一个feature。

因此我只要new一个Sputnik,通过反射把SpecInfo中的信息拿出来,就能拿到按顺序所有排序的方法和对应编译后的方法名了了。

 public static List<String> getAllSpecFeatures(String className) {
List<String> ret = new ArrayList<>();
Class klass = Class.forName(className);
Sputnik runner = new Sputnik(klass);
Method m = runner.class.getDeclaredMethod("getSpec");
m.setAccessible(true);
SpecInfo specInfo = m.invoke(runner);
List<FeatureInfo> featureInfos = specInfo.getAllFeatures();
for (FeatureInfo featureInfo : featureInfos) {
// original groovy method name
ret.add(featureInfo.getName()); // compiled method name, format like "$spock_feature_0_0"
println(featureInfo.featureMethod.reflection.name)
}
return ret;
}

Groovy 反射字符串常量方法的更多相关文章

  1. 字符串常量池和String.intern()方法在jdk1.6、1.7、1.8中的变化

    字符串常量池也是运行时常量池 jdk1.6中,它是在方法区中,属于“永久代” jdk1.7中,它被移除方法区,放在java堆中 jdk1.8中,取消了“永久代”,将常量池放在元空间,与堆独立了 pub ...

  2. java中字符串“不可变性”的破坏,使用反射破坏final属性。以及涉及到字符串常量池的问题。

    大家都清楚java中String类是不可变的,它的定义中包含final关键字.一旦被创建,值就不能被改变(引用是可以改变的). 但这种“不可变性”不是完全可靠的,可以通过反射机制破坏.参考一下代码: ...

  3. Java中Pattern类的quote方法将任何字符串(包括正则表达式)都转换成字符串常量,不具有任何匹配功能

    Java中Pattern类的quote方法将任何字符串(包括正则表达式)都转换成字符串常量,不具有任何匹配功能. 下面是个例子: import org.junit.Test; import java. ...

  4. 对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

    在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...

  5. 理解Java字符串常量池与intern()方法

    String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo ...

  6. Java 字符串常量存放在堆内存还是JAVA方法区?

    JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池. JDK1.8开始,取消了Java方法区,取而代之的是位于直接内 ...

  7. 从HotSpot VM源码看字符串常量池(StringTable)和intern()方法

    引言 字符串常量池(StringTable)是JVM中一个重要的结构,它有助于避免重复创建相同内容的String对象.那么StringTable是怎么实现的?"把字符串加入到字符串常量池中& ...

  8. 在JavaScript里嵌入大量字符串常量的方法

    [转]在JavaScript文件里嵌入大量字符串常量是经常遇到的事.有时为了省事,就把一些界面的HTML和CSS直接写在JS文件里.数量少还好,多的话就密密麻麻的一坨文字,讲究美观的文艺青年们,会用大 ...

  9. 使用Microsoft Roslyn提取C#和VB.NET源代码中的字符串常量

    Microsoft Roslyn是微软.NET“编译器即服务(Compiler as a Service)”的主要产品,它提供了开放的编译器API,并为源代码产生.分析和重构提供了新一代的语言对象模型 ...

随机推荐

  1. Git 从 master 分支拉新分支开发

    一. 切换到被copy的分支(master),并且从远端拉取最新版本 $git checkout master $git pull 二.从当前分支拉copy开发分支 $git checkout -b ...

  2. 跳跃表Skip List的原理

    1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...

  3. 跨域资源共享 CORS 详解(转自阮一峰博客)

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing). 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从 ...

  4. net core体系-Xamarin-1概要

    大家在开发领域都知道Java是跨平台的,但是很多人认为.NET是只能在Windows下运行,不具有跨平台的特性,这种说法其实是不妥的. .NET其实在设计之初也是考虑像Java一样跨平台的,我们知道. ...

  5. Unknown lifecycle phase "mvn"

    Unknown lifecycle phase "mvn" maven执行命令错误  : 执行输入命令即可,不需要添加 mvn 此处不需要写mvn,而是执行写compile就行,否 ...

  6. kmp基础 ekmp

    +]; int lenp,lens; +];//可以是char 也可以是string +]; void getnext() { nex[]=-; ,j=; ) { ||p[j]==p[k]) nex[ ...

  7. day21 模块 异常处理

    常用模块:http://www.cnblogs.com/Eva-J/articles/7228075.html 今日概要: #time # —— 时间:时间戳 字符串 结构化时间 #collectio ...

  8. union表关联模糊查询servlet,action方法

    2018-11-14 servletxml层 public String getSql(String keyword) { StringBuffer sqlSb = new StringBuffer( ...

  9. Gson的两种实例化方式:

    2018-11-13   09:21:44 Gson的两种实例化方式: 1: 使用new Gson(); 普通实例化方式,不能配置定制化选项 Gson gson = new Gson(); 2: 通过 ...

  10. Tomcat启动分析(转自:http://docs.huihoo.com/apache/tomcat/heavyz/01-startup.html)

    Tomcat启动分析 1 - Tomcat Server的组成部分 1.1 - Server A Server element represents the entire Catalina servl ...