@@ -134,11 +134,18 @@ public abstract class ClassUtils {
134
134
*/
135
135
private static final Set <Class <?>> javaLanguageInterfaces ;
136
136
137
+ /**
138
+ * Cache for equivalent methods on a interface implemented by the declaring class.
139
+ * <p>A {@code null} value signals that no interface method was found for the key.
140
+ */
141
+ private static final Map <Method , Method > interfaceMethodCache = new ConcurrentReferenceHashMap <>(256 );
142
+
137
143
/**
138
144
* Cache for equivalent methods on a public interface implemented by the declaring class.
139
145
* <p>A {@code null} value signals that no public interface method was found for the key.
146
+ * @since 6.2
140
147
*/
141
- private static final Map <Method , Method > interfaceMethodCache = new ConcurrentReferenceHashMap <>(256 );
148
+ private static final Map <Method , Method > publicInterfaceMethodCache = new ConcurrentReferenceHashMap <>(256 );
142
149
143
150
/**
144
151
* Cache for equivalent public methods in a public declaring type within the type hierarchy
@@ -1403,7 +1410,8 @@ public static Method getMostSpecificMethod(Method method, @Nullable Class<?> tar
1403
1410
* @param method the method to be invoked, potentially from an implementation class
1404
1411
* @return the corresponding interface method, or the original method if none found
1405
1412
* @since 5.1
1406
- * @deprecated in favor of {@link #getPubliclyAccessibleMethodIfPossible(Method, Class)}
1413
+ * @see #getPubliclyAccessibleMethodIfPossible(Method, Class)
1414
+ * @deprecated in favor of {@link #getInterfaceMethodIfPossible(Method, Class)}
1407
1415
*/
1408
1416
@ Deprecated
1409
1417
public static Method getInterfaceMethodIfPossible (Method method ) {
@@ -1421,38 +1429,45 @@ public static Method getInterfaceMethodIfPossible(Method method) {
1421
1429
* @since 5.3.16
1422
1430
* @see #getPubliclyAccessibleMethodIfPossible(Method, Class)
1423
1431
* @see #getMostSpecificMethod
1424
- * @deprecated in favor of {@link #getPubliclyAccessibleMethodIfPossible(Method, Class)}
1425
1432
*/
1426
- @ Deprecated (since = "6.2" )
1427
1433
public static Method getInterfaceMethodIfPossible (Method method , @ Nullable Class <?> targetClass ) {
1434
+ return getInterfaceMethodIfPossible (method , targetClass , false );
1435
+ }
1436
+
1437
+ private static Method getInterfaceMethodIfPossible (Method method , @ Nullable Class <?> targetClass ,
1438
+ boolean requirePublicInterface ) {
1439
+
1428
1440
Class <?> declaringClass = method .getDeclaringClass ();
1429
- if (!Modifier .isPublic (method .getModifiers ()) || declaringClass .isInterface ()) {
1441
+ if (!Modifier .isPublic (method .getModifiers ()) || (declaringClass .isInterface () &&
1442
+ (!requirePublicInterface || Modifier .isPublic (declaringClass .getModifiers ())))) {
1430
1443
return method ;
1431
1444
}
1432
1445
String methodName = method .getName ();
1433
1446
Class <?>[] parameterTypes = method .getParameterTypes ();
1434
1447
1448
+ Map <Method , Method > methodCache = (requirePublicInterface ? publicInterfaceMethodCache : interfaceMethodCache );
1435
1449
// Try cached version of method in its declaring class
1436
- Method result = interfaceMethodCache .computeIfAbsent (method ,
1437
- key -> findInterfaceMethodIfPossible ( methodName , parameterTypes , declaringClass , Object .class ));
1450
+ Method result = methodCache .computeIfAbsent (method , key -> findInterfaceMethodIfPossible (
1451
+ methodName , parameterTypes , declaringClass , Object .class , requirePublicInterface ));
1438
1452
if (result == null && targetClass != null ) {
1439
1453
// No interface method found yet -> try given target class (possibly a subclass of the
1440
1454
// declaring class, late-binding a base class method to a subclass-declared interface:
1441
1455
// see e.g. HashMap.HashIterator.hasNext)
1442
- result = findInterfaceMethodIfPossible (methodName , parameterTypes , targetClass , declaringClass );
1456
+ result = findInterfaceMethodIfPossible (
1457
+ methodName , parameterTypes , targetClass , declaringClass , requirePublicInterface );
1443
1458
}
1444
1459
return (result != null ? result : method );
1445
1460
}
1446
1461
1447
1462
@ Nullable
1448
1463
private static Method findInterfaceMethodIfPossible (String methodName , Class <?>[] parameterTypes ,
1449
- Class <?> startClass , Class <?> endClass ) {
1464
+ Class <?> startClass , Class <?> endClass , boolean requirePublicInterface ) {
1450
1465
1451
1466
Class <?> current = startClass ;
1452
1467
while (current != null && current != endClass ) {
1453
1468
for (Class <?> ifc : current .getInterfaces ()) {
1454
1469
try {
1455
- if (Modifier .isPublic (ifc .getModifiers ())) {
1470
+ if (! requirePublicInterface || Modifier .isPublic (ifc .getModifiers ())) {
1456
1471
return ifc .getMethod (methodName , parameterTypes );
1457
1472
}
1458
1473
}
@@ -1500,7 +1515,7 @@ public static Method getPubliclyAccessibleMethodIfPossible(Method method, @Nulla
1500
1515
return method ;
1501
1516
}
1502
1517
1503
- Method interfaceMethod = getInterfaceMethodIfPossible (method , targetClass );
1518
+ Method interfaceMethod = getInterfaceMethodIfPossible (method , targetClass , true );
1504
1519
// If we found a method in a public interface, return the interface method.
1505
1520
if (!interfaceMethod .equals (method )) {
1506
1521
return interfaceMethod ;
0 commit comments