博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
velocity 之坑:不同枚举类(enum)有相同的静态(static)方法,无法访问第二个枚举类...
阅读量:6877 次
发布时间:2019-06-26

本文共 2489 字,大约阅读时间需要 8 分钟。

  hot3.png

问题描述:

当用velocity,需要在同一个页面调用两个不同java枚举类的静态方法时,如果有两个枚举类的静态方法同名,则页面上的第二个静态方法调用始终是访问的第一个枚举类方法。

以下是国外朋友详细的问题陈述:

I am using Apache Velocity where I'm calling static Methods on Enums. Now I have two Enums which both have the same static Method-Name. When I call the static Method on the first Enum all works fine. When I call the Method on the second Enum, I get the result of the first Enum.

Example:

public enum A{

  VALUE_A1(1), VALUE_A2(2);

  private int id;

  private A(int id){

      this.id = id;

  }

  public static A getById(int id){

    for (A a : values()){

      if (a.id==id){

        return a;

      }

    }

    return null;

  }

}

public enum B{

  VALUE_B1(1), VALUE_B2(2);

  private int id;

  private B(int id){

      this.id = id;

  }

  public static B getById(int id){

      ...

  }

}

I initialized both in Velocity the same way:

VelocityContext context = new VelocityContext();

context.put("A", A.class);

context.put("B", B.class);

context.put("value1", 1);

context.put("value2", 2);

When I now call these Methods in my template, there are some issues. Calling the Method getById() on Enum A works fine. Calling it on Enum B gives me the value of enum A as a result.

$A.getById($value1)

$B.getById($value1)

results in 

VALUE_A1

VALUE_A1

and not in 

VALUE_A1

VALUE_B1

as expected

When I rename the Method in B and change the template properly, all works fine, but thats not what I want. Am I missing something? Or is it a bug in Apache Velocity?

解决方案:

context.put("A", A.values()[0]);

context.put("B", B.values()[0]);

深入分析:

velocity解析静态类时,会调用静态类的 staticClass.getClass()去缓存静态方法调用,staticClass.getClass()始终是java.lang.Class, 所以velocity内部缓存的所有静态类,只要静态方法签名相同,都默认走缓存获取第一个具有相同方法签名的类对象,调用该类对象的静态方法。

velocity 1.7 源码:

org.apache.velocity.util.ClassUtils.getMethod(String, Object[], Class[], Object, InternalContextAdapter, SimpleNode, boolean):line 189

/*

       * like ASTIdentifier, if we have cache information, and the Class of

       * Object o is the same as that in the cache, we are safe.

       */

      if (icd != null && (o != null && icd.contextData == o.getClass())) //此处o.getClass() == java.lang.Class

      {

        /*

         * get the method from the cache

         */

        method = (VelMethod) icd.thingy;

      } 

org.apache.velocity.util.ClassUtils.getMethod(String, Object[], Class[], Object, InternalContextAdapter, SimpleNode, boolean):line 208

 if ((method != null) && (o != null))

        {

          icd = new IntrospectionCacheData();

          icd.contextData = o.getClass(); //此处任何静态类(eg:context.put("A", A.class);)的A.class.getClass() 都相同

          icd.thingy = method;

          context.icachePut(mck, icd);

        }

转载于:https://my.oschina.net/fdhay/blog/633095

你可能感兴趣的文章
mysql5.6.22的my.ini文件配置
查看>>
如何排查数据库数据统计错误的原因?
查看>>
部署Eclipse金蝶项目
查看>>
java注解原理
查看>>
Android Activity生命周期
查看>>
我的友情链接
查看>>
Mac OS X 10.9下安装Wireshark
查看>>
在真机里安装 ubuntu 14.04和一些常用的软件(一)
查看>>
亿级用户下的新浪微博平台架构
查看>>
UISwitch
查看>>
门窗密封条安装图
查看>>
MySQL中 enum 插入的时候注意事项
查看>>
Python 36计
查看>>
linux下发送邮件
查看>>
LINUX的LVM使用
查看>>
linux下磁盘管理命令汇总
查看>>
CentOS7 下PXE+kickstart自动化安装系统
查看>>
Linux 学习路线指南
查看>>
“跨界”后的微博会更好吗?
查看>>
高效的加载大尺寸图片
查看>>