为什么 mybatis 的 MetaObject 类不支持 “[0]” 这样的路径?

Why the mybatis's MetaObject Class not support the path like "[0]"?

提问人:vate 提问时间:11/17/2023 最后编辑:vate 更新时间:11/21/2023 访问量:23

问:

我正在阅读mybatis代码,然后我发现MetaObject是一个非常重要的类。 我们用它来访问 Object 的属性(甚至是嵌套属性)。 如果我们有这样的对象:

{
  "a": {
      "b":[1,2,3]
  }
}

当我们想得到 b[0] 的值时; 我们总是这样使用这种形式:

metaObject.getValue("a.b[0]");

一切都很好。

但是,如果我有这样的收藏:

// create a single element list: [1]
MetaObject mo = MetaObject.forObject(
      new ArrayList<String>() {{add("1");}},
      new DefaultObjectFactory(),
      new DefaultObjectWrapperFactory(),
      new DefaultReflectorFactory()
);

// If I want get the element of collection.
// It will cause an error.
System.out.println(metaObject1.getValue("[0]"));

// Because the CollectionWrapper is not implements the 'get' method.
// the code is following:
public Object get(PropertyTokenizer prop) {
  throw new UnsupportedOperationException();
}

所以,我不明白为什么我们不支持这种方式来查找像“[0]”这样的集合元素。

现在我们只支持从外部对象(如“b[0]”)访问集合的元素,而 b 是对象的属性。

有人知道吗?

米巴蒂斯

评论

0赞 ave 11/17/2023
java.util.Collection不保证顺序,也不允许按索引访问。 确实如此。通常,开发人员需要使用集合中的所有项,因此工作正常。如果出于某种原因只需要列表中的一项,您仍然可以使用 and/or 属性。java.util.List<foreach><foreach>beginend

答:

0赞 vate 11/21/2023 #1

核心原因是“java.util.Collection 不保证顺序,不允许按索引访问”。

当我们访问 bean 或 map 的集合属性时,它将被强制转换为 Array 或 List。

如果 accessed 的集合属性不是 Array 或 List,我们将抛出 ReflectionException。

因此,我们不必担心收集的顺序。

核心代码如下:

protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
    if (collection instanceof Map) {
      return ((Map) collection).get(prop.getIndex());
    } else {
      int i = Integer.parseInt(prop.getIndex());
      if (collection instanceof List) {
        return ((List) collection).get(i);
      } else if (collection instanceof Object[]) {
        return ((Object[]) collection)[i];
      } else if (collection instanceof char[]) {
        return ((char[]) collection)[i];
      } else if (collection instanceof boolean[]) {
        return ((boolean[]) collection)[i];
      } else if (collection instanceof byte[]) {
        return ((byte[]) collection)[i];
      } else if (collection instanceof double[]) {
        return ((double[]) collection)[i];
      } else if (collection instanceof float[]) {
        return ((float[]) collection)[i];
      } else if (collection instanceof int[]) {
        return ((int[]) collection)[i];
      } else if (collection instanceof long[]) {
        return ((long[]) collection)[i];
      } else if (collection instanceof short[]) {
        return ((short[]) collection)[i];
      } else {
        throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
      }
    }
  }