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());

Reply via email to