This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new 0c4093928 Fix FieldUtils.getField false ambiguity on inherited
interface field (#1748)
0c4093928 is described below
commit 0c409392897ac41e06f76ecdd1c639e4bee52505
Author: alhuda <[email protected]>
AuthorDate: Mon Jul 13 19:57:44 2026 +0530
Fix FieldUtils.getField false ambiguity on inherited interface field (#1748)
---
.../apache/commons/lang3/reflect/FieldUtils.java | 2 +-
.../commons/lang3/reflect/FieldUtilsTest.java | 29 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
b/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
index 4e3203f0b..bbb678193 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
@@ -217,7 +217,7 @@ public static Field getField(final Class<?> cls, final
String fieldName, final b
for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
try {
final Field test = class1.getField(fieldName);
- Validate.isTrue(match == null,
+ Validate.isTrue(match == null || match.equals(test),
"Reference to field %s is ambiguous relative to %s; a
matching field exists on two or more implemented interfaces.", fieldName, cls);
match = test;
} catch (final NoSuchFieldException ignored) {
diff --git a/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
b/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
index 4666ec7fb..65b3f6507 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
@@ -73,6 +73,26 @@ class FieldUtilsTest extends AbstractLangTest {
private PrivatelyShadowedChild privatelyShadowedChild;
private final Class<? super PublicChild> parentClass =
PublicChild.class.getSuperclass();
+ interface InterfaceWithConstant {
+ int CONSTANT = 42;
+ }
+
+ interface SubInterfaceA extends InterfaceWithConstant {
+ // inherits CONSTANT
+ }
+
+ interface SubInterfaceB extends InterfaceWithConstant {
+ // inherits CONSTANT
+ }
+
+ static class MultiPathToConstant implements SubInterfaceA, SubInterfaceB {
+ // CONSTANT is reachable through both parents and through the
grandparent interface
+ }
+
+ static class SinglePathToConstant implements SubInterfaceA {
+ // CONSTANT is reachable through the sub-interface and its
super-interface
+ }
+
/**
* Reads the {@code @deprecated} notice on {@link
FieldUtils#removeFinalModifier(Field, boolean)}.
*
@@ -109,6 +129,15 @@ void testAmbig() {
assertIllegalArgumentException(() -> FieldUtils.getField(Ambig.class,
"VALUE"));
}
+ @Test
+ void testGetFieldInheritedThroughMultipleInterfacePaths() {
+ // A field reached through more than one interface path resolves to
the same Field, so it is not ambiguous.
+ assertEquals(InterfaceWithConstant.class,
FieldUtils.getField(SinglePathToConstant.class,
"CONSTANT").getDeclaringClass());
+ assertEquals(InterfaceWithConstant.class,
FieldUtils.getField(MultiPathToConstant.class, "CONSTANT").getDeclaringClass());
+ // A genuine clash of two different fields on unrelated interfaces is
still ambiguous.
+ assertIllegalArgumentException(() -> FieldUtils.getField(Ambig.class,
"VALUE"));
+ }
+
@Test
void testConstructor() {
assertNotNull(new FieldUtils());