【问题标题】:Set fields with reflection - String has no valueOf(String) method使用反射设置字段 - 字符串没有 valueOf(String) 方法
【发布时间】:2010-05-30 14:12:17
【问题描述】:

我正在通过反射设置 Object this 的公共字段。字段名称和值都以String 给出。我使用了几种不同的字段类型:BooleanIntegerFloatDouble、一个自己的enum 和一个String

它适用于所有这些String 除外。抛出的异常是不存在具有签名String.valueOf(String) 的方法...现在我使用肮脏的instanceof 解决方法来检测每个字段是否是字符串,在这种情况下只需将值复制到字段。

private void setField(String field, String value) throws Exception {
   Field wField = this.getClass().getField(field);

   if(wField.get(this) instanceof String){ //TODO dirrrrty hack
    //stupid workaround as java.lang.String.valueOf(java.lang.String) fails...
    wField.set(this, value);
   }else{
    Method parseMethod = wField.getType().getMethod("valueOf", new Class[]{String.class});
    wField.set(this, parseMethod.invoke(wField, value));
   }
 }

任何想法如何避免这种解决方法?

你认为java.lang.String应该支持valueOf(String)这个方法吗?

谢谢。

【问题讨论】:

  • 值得一提的是,所有这些对象(枚举除外)都有一元字符串构造函数。因此,您可以切换到在所有情况下都使用它们,并且仅将 valueOf 用于您的枚举,如果这看起来更干净的话。

标签: java string reflection value-of


【解决方案1】:

如您所见,没有String.valueOf(String)。但是,我不会认为您的实现是 hack,只是认识到 JDK 类中的轻微不一致。

对于更健壮的字符串到对象的转换,您可以考虑使用PropertyEditors,它直接支持字符串到对象的转换 - 默认提供基本类型和字符串的实现。)然后您的解析方法将是一致的,并且可扩展以处理不同种类。更好的是 Commons ConvertSpring 3 Type Converters 中的转换类,因为它们完全专注于转换,而不是属性的 GUI 编辑。

【讨论】:

  • Spring 正在使用属性编辑器,不是吗?顺便说一句,它们绝对是您想要的。
  • Spring 确实使用了 PropertyEditors,但在 Spring 3.x 中还有比 PropertyEditors 更“干净”的新类型转换类。
【解决方案2】:

任何想法如何避免这种解决方法?

这很大程度上取决于parseMethod的实现。

你认为java.lang.String应该支持valueOf(String)方法吗?

为了什么?那将是一个无操作,只是返回它的参数。

【讨论】:

  • parseMethod 是 valueOf(String)。所以我没有自己实现。是的,这将是一个无操作,但它会使 valueOf 更普遍可用恕我直言。至少在这种情况下。但也许还有另一个我不知道的选择。
  • @fabb,它只能在反射的特殊情况下使用,所以大多数 Java 开发人员永远不需要它。恕我直言,您展示的解决方法是可以忍受的。
【解决方案3】:

你认为java.lang.String应该支持valueOf(String)这个方法吗?

没有。它在反射之外几乎没有任何价值,而且无论如何都不应该鼓励反射(Effective Java 2nd Edition,Item 53:Prefer interfaces to reflection)。

【讨论】:

  • 哦,拜托,只是因为布洛赫说这并不成立。反射是一个强大而美妙的工具。然而,我承认这个特殊的实例似乎并不是它最伟大的时刻。
【解决方案4】:

如果是字符串:

方法 parseMethod = wField.getType().getMethod("valueOf", new Class[]{Object.class});

wField.set(this, parseMethod.invoke(wField, value));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-28
    • 2013-05-17
    • 2010-11-08
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 2014-10-13
    • 2020-07-16
    相关资源
    最近更新 更多