Java反思,有没有简单的方法通过'field path'获取字段值?
Java reflection, is there an easy way to get field value by 'field path'?
我有一个非常复杂的 class,比如,
classA {
public classB b;
}
classB {
public classC c;
}
classC {
public List<classD> d;
}
...
现在,给定一个 classA 的实例,以及一个像 'b.c.d.e.f.g' 这样的字段路径,是否有一种简单的方法可以通过反射获取目标字段值?任何现有的图书馆或什么?
非常感谢。
没有一种“简单”的方法(并且绝对没有一种简单的方法可以通过使用像 b.c.d.e.f
这样的字段路径导航到 classD
元素的列表,因为(在某些情况下点)你需要指定你正在查看的 List
中的哪个元素。
不过,我们可以使用反射来向下导航字段队列。尽管在这个简单的示例中,我们无法从 List
中选取元素,但我们仍然可以检查 List
本身的属性,例如 size
.
(下面的例子直接访问这个私有变量——绝对不建议——但你的问题是关于反思,所以为了说明的目的,我们将这些其他重要的问题放在一边)
对于这个特定的示例,结果输出将是 RESULT of b.c.d.size: 3
,因为我们在初始化变量时将三个 new ClassD()
对象填充到 List
中。
public static void main(final String args[]) throws Exception
{
// Initialize all variables
final ClassA a = new ClassA();
a.b = new ClassB();
a.b.c = new ClassC();
a.b.c.d = new ArrayList<>(Arrays.asList(new ClassD(), new ClassD(), new ClassD()));
// Traverse these member variables
final String fieldPath = "b.c.d.size";
// Build the list of paths from the string
final Queue<String> fieldPaths = new ArrayDeque<>(Arrays.asList(fieldPath.split("\.")));
// Display the output
System.out.println("RESULT of ".concat(fieldPath).concat(": ").concat(discover(a, fieldPaths).toString()));
}
public static Object discover(final Object o, final Queue<String> fieldPaths) throws Exception
{
// End of the queue, return the object found most recently
if (fieldPaths.isEmpty())
{
return o;
}
final String nextFieldPath = fieldPaths.remove();
final Field f = o.getClass().getDeclaredField(nextFieldPath);
// Go ahead and access private/protected data anyway... it's fine! what could go wrong
f.setAccessible(true);
return discover(f.get(o), fieldPaths);
}
protected static class ClassA
{
public ClassB b;
}
protected static class ClassB
{
public ClassC c;
}
protected static class ClassC
{
public List<ClassD> d;
}
protected static class ClassD
{
// Empty block
}
谢谢大家 post。
谢谢 Tim,commons-beanutils 在处理 pojo 类 时很有帮助,它在 List/Map 领域工作得很好。
这几乎是我所需要的,除了一些极端情况,例如,当给出一个没有提供索引的列表时。
我认为要走的路是在 commons-beanutils 的帮助下编写我自己的工具。
我有一个非常复杂的 class,比如,
classA {
public classB b;
}
classB {
public classC c;
}
classC {
public List<classD> d;
}
...
现在,给定一个 classA 的实例,以及一个像 'b.c.d.e.f.g' 这样的字段路径,是否有一种简单的方法可以通过反射获取目标字段值?任何现有的图书馆或什么?
非常感谢。
没有一种“简单”的方法(并且绝对没有一种简单的方法可以通过使用像 b.c.d.e.f
这样的字段路径导航到 classD
元素的列表,因为(在某些情况下点)你需要指定你正在查看的 List
中的哪个元素。
不过,我们可以使用反射来向下导航字段队列。尽管在这个简单的示例中,我们无法从 List
中选取元素,但我们仍然可以检查 List
本身的属性,例如 size
.
(下面的例子直接访问这个私有变量——绝对不建议——但你的问题是关于反思,所以为了说明的目的,我们将这些其他重要的问题放在一边)
对于这个特定的示例,结果输出将是 RESULT of b.c.d.size: 3
,因为我们在初始化变量时将三个 new ClassD()
对象填充到 List
中。
public static void main(final String args[]) throws Exception
{
// Initialize all variables
final ClassA a = new ClassA();
a.b = new ClassB();
a.b.c = new ClassC();
a.b.c.d = new ArrayList<>(Arrays.asList(new ClassD(), new ClassD(), new ClassD()));
// Traverse these member variables
final String fieldPath = "b.c.d.size";
// Build the list of paths from the string
final Queue<String> fieldPaths = new ArrayDeque<>(Arrays.asList(fieldPath.split("\.")));
// Display the output
System.out.println("RESULT of ".concat(fieldPath).concat(": ").concat(discover(a, fieldPaths).toString()));
}
public static Object discover(final Object o, final Queue<String> fieldPaths) throws Exception
{
// End of the queue, return the object found most recently
if (fieldPaths.isEmpty())
{
return o;
}
final String nextFieldPath = fieldPaths.remove();
final Field f = o.getClass().getDeclaredField(nextFieldPath);
// Go ahead and access private/protected data anyway... it's fine! what could go wrong
f.setAccessible(true);
return discover(f.get(o), fieldPaths);
}
protected static class ClassA
{
public ClassB b;
}
protected static class ClassB
{
public ClassC c;
}
protected static class ClassC
{
public List<ClassD> d;
}
protected static class ClassD
{
// Empty block
}
谢谢大家 post。
谢谢 Tim,commons-beanutils 在处理 pojo 类 时很有帮助,它在 List/Map 领域工作得很好。
这几乎是我所需要的,除了一些极端情况,例如,当给出一个没有提供索引的列表时。
我认为要走的路是在 commons-beanutils 的帮助下编写我自己的工具。