我正在阅读mybatis代码,我发现MetaObject是一个非常重要的类。 我们用它来访问对象的属性(甚至是嵌套属性)。 如果我们有一个像这样的对象:
{
"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是对象的属性。
有人知道吗?
核心原因是“java.util.Collection不保证顺序,不允许通过索引访问。”。
当我们访问bean或map的集合属性时,它将被转换为Array或List。
如果访问的集合属性不是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.");
}
}
}