View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.reflect;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
20  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNotSame;
25  import static org.junit.jupiter.api.Assertions.assertNull;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.junit.jupiter.api.Assertions.assertTrue;
29  
30  import java.awt.Color;
31  import java.lang.reflect.Method;
32  import java.lang.reflect.Modifier;
33  import java.lang.reflect.Type;
34  import java.nio.file.Files;
35  import java.nio.file.LinkOption;
36  import java.nio.file.Path;
37  import java.util.Arrays;
38  import java.util.Date;
39  import java.util.HashMap;
40  import java.util.Iterator;
41  import java.util.List;
42  import java.util.Map;
43  
44  import org.apache.commons.lang3.AbstractLangTest;
45  import org.apache.commons.lang3.ArrayUtils;
46  import org.apache.commons.lang3.ClassUtils;
47  import org.apache.commons.lang3.ClassUtils.Interfaces;
48  import org.apache.commons.lang3.math.NumberUtils;
49  import org.apache.commons.lang3.mutable.Mutable;
50  import org.apache.commons.lang3.mutable.MutableObject;
51  import org.apache.commons.lang3.reflect.testbed.Annotated;
52  import org.apache.commons.lang3.reflect.testbed.GenericConsumer;
53  import org.apache.commons.lang3.reflect.testbed.GenericParent;
54  import org.apache.commons.lang3.reflect.testbed.PublicChild;
55  import org.apache.commons.lang3.reflect.testbed.PublicSubBeanOtherPackage;
56  import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
57  import org.apache.commons.lang3.tuple.ImmutablePair;
58  import org.junit.jupiter.api.BeforeEach;
59  import org.junit.jupiter.api.Test;
60  import org.junit.jupiter.params.ParameterizedTest;
61  import org.junit.jupiter.params.provider.ValueSource;
62  
63  /**
64   * {@link Tests MethodUtils}.
65   */
66  class MethodUtilsTest extends AbstractLangTest {
67  
68      protected abstract static class AbstractGetMatchingMethod implements InterfaceGetMatchingMethod {
69          public abstract void testMethod5(Exception exception);
70      }
71  
72      protected abstract static class AbstractGetMatchingMethod2 implements InterfaceGetMatchingMethod {
73          @Override
74          public void testMethod6() { }
75      }
76  
77      public static class ChildObject extends ParentObject implements PackagePrivateEmptyInterface {
78      }
79  
80      private static final class ConcreteGetMatchingMethod2 extends AbstractGetMatchingMethod2 { }
81  
82      private static final class ConcreteGetMatchingMethod22 extends AbstractGetMatchingMethod2 {
83          @Override
84          public void testMethod6() { }
85      }
86  
87      private static final class GetMatchingMethodClass {
88  
89          public void testMethod() {
90          }
91  
92          public void testMethod(final long aLong) {
93          }
94  
95          public void testMethod(final Long aLong) {
96          }
97  
98          public void testMethod2(final Color aColor) {
99          }
100 
101         public void testMethod2(final long aLong) {
102         }
103 
104         public void testMethod2(final Long aLong) {
105         }
106 
107         public void testMethod3(final long aLong, final Long anotherLong) {
108         }
109 
110         public void testMethod3(final Long aLong, final long anotherLong) {
111         }
112 
113         public void testMethod3(final Long aLong, final Long anotherLong) {
114         }
115 
116         public void testMethod4(final Color aColor1, final Color aColor2) {
117         }
118 
119         public void testMethod4(final Long aLong, final Long anotherLong) {
120         }
121     }
122 
123     private static final class GetMatchingMethodImpl extends AbstractGetMatchingMethod {
124         @Override
125         public void testMethod5(final Exception exception) {
126         }
127     }
128 
129     public static class GrandParentObject {
130     }
131     public static class InheritanceBean {
132         public void testOne(final GrandParentObject obj) {
133         }
134 
135         public void testOne(final Object obj) {
136         }
137 
138         public void testOne(final ParentObject obj) {
139         }
140 
141         public void testTwo(final GrandParentObject obj) {
142         }
143 
144         public void testTwo(final Object obj) {
145         }
146 
147         public void testTwo(final PackagePrivateEmptyInterface obj) {
148         }
149     }
150 
151     interface InterfaceGetMatchingMethod {
152         default void testMethod6() {
153         }
154     }
155     private static final class MethodDescriptor {
156         final Class<?> declaringClass;
157         final String name;
158         final Type[] parameterTypes;
159 
160         MethodDescriptor(final Class<?> declaringClass, final String name, final Type... parameterTypes) {
161             this.declaringClass = declaringClass;
162             this.name = name;
163             this.parameterTypes = parameterTypes;
164         }
165     }
166 
167     interface PackagePrivateEmptyInterface {
168         // empty
169     }
170 
171     public static class ParentObject extends GrandParentObject {
172         // empty
173     }
174 
175     private interface PrivateEmptyInterface {
176         // empty
177     }
178 
179     public static class PublicImpl1OfPackagePrivateEmptyInterface implements PackagePrivateEmptyInterface {
180         // empty
181     }
182 
183     public static class PublicImpl2OfPackagePrivateEmptyInterface implements PackagePrivateEmptyInterface {
184         // empty
185     }
186 
187     public static class TestBean {
188 
189         public static String bar() {
190             return "bar()";
191         }
192 
193         public static String bar(final double d) {
194             return "bar(double)";
195         }
196 
197         public static String bar(final int i) {
198             return "bar(int)";
199         }
200 
201         public static String bar(final Integer i) {
202             return "bar(Integer)";
203         }
204 
205         public static String bar(final Integer i, final String... s) {
206             return "bar(Integer, String...)";
207         }
208 
209         public static String bar(final long... s) {
210             return "bar(long...)";
211         }
212 
213         public static String bar(final Object o) {
214             return "bar(Object)";
215         }
216 
217         public static String bar(final String s) {
218             return "bar(String)";
219         }
220 
221         public static String bar(final String... s) {
222             return "bar(String...)";
223         }
224 
225         // This method is overloaded for the wrapper class for every numeric primitive type, plus the common
226         // supertype Number
227         public static String numOverload(final Byte... args) {
228             return "Byte...";
229         }
230 
231         public static String numOverload(final Double... args) {
232             return "Double...";
233         }
234 
235         public static String numOverload(final Float... args) {
236             return "Float...";
237         }
238 
239         public static String numOverload(final Integer... args) {
240             return "Integer...";
241         }
242 
243         public static String numOverload(final Long... args) {
244             return "Long...";
245         }
246 
247         public static String numOverload(final Number... args) {
248             return "Number...";
249         }
250 
251         public static String numOverload(final Short... args) {
252             return "Short...";
253         }
254 
255         public static void oneParameterStatic(final String s) {
256             // empty
257         }
258 
259         public static String staticInt(final int intArg) {
260             return "static int";
261         }
262 
263         public static String staticIntIntVarArg(final int intArg, final int... args) {
264             return "static int, int...";
265         }
266 
267         public static String staticIntLongVarArg(final int intArg, final long... args) {
268             return "static int, long...";
269         }
270 
271         public static String staticIntStringVarArg(final int intArg, final String... args) {
272             return "static int, String...";
273         }
274 
275         public static String staticPackagePrivateEmptyInterface(final PackagePrivateEmptyInterface... args) {
276             return "static PackagePrivateEmptyInterface...";
277         }
278 
279         public static String varOverload(final Boolean... args) {
280             return "Boolean...";
281         }
282 
283         // This method is overloaded for the wrapper class for every primitive type, plus the common supertypes
284         // Number and Object. This is an acid test since it easily leads to ambiguous methods.
285         public static String varOverload(final Byte... args) {
286             return "Byte...";
287         }
288 
289         public static String varOverload(final Character... args) {
290             return "Character...";
291         }
292 
293         public static String varOverload(final Double... args) {
294             return "Double...";
295         }
296 
297         public static String varOverload(final Float... args) {
298             return "Float...";
299         }
300 
301         public static String varOverload(final Integer... args) {
302             return "Integer...";
303         }
304 
305         public static String varOverload(final Long... args) {
306             return "Long...";
307         }
308 
309         public static String varOverload(final Number... args) {
310             return "Number...";
311         }
312 
313         public static String varOverload(final Object... args) {
314             return "Object...";
315         }
316 
317         public static String varOverload(final Short... args) {
318             return "Short...";
319         }
320 
321         public static String varOverload(final String... args) {
322             return "String...";
323         }
324 
325         public static ImmutablePair<String, Object[]> varOverloadEchoStatic(final Number... args) {
326             return new ImmutablePair<>("Number...", args);
327         }
328 
329         public static ImmutablePair<String, Object[]> varOverloadEchoStatic(final String... args) {
330             return new ImmutablePair<>("String...", args);
331         }
332 
333         static void verify(final ImmutablePair<String, Object[]> a, final ImmutablePair<String, Object[]> b) {
334             assertEquals(a.getLeft(), b.getLeft());
335             assertArrayEquals(a.getRight(), b.getRight());
336         }
337 
338         static void verify(final ImmutablePair<String, Object[]> a, final Object obj) {
339             @SuppressWarnings("unchecked")
340             final ImmutablePair<String, Object[]> pair = (ImmutablePair<String, Object[]>) obj;
341             verify(a, pair);
342         }
343 
344         boolean unboxBooleanArray;
345 
346         boolean unboxByteArray;
347 
348         boolean unboxCharArray;
349 
350         boolean unboxDoubleArray;
351 
352         boolean unboxFloatArray;
353 
354         boolean unboxIntArray;
355 
356         boolean unboxLongArray;
357 
358         boolean unboxShortArray;
359 
360         public String foo() {
361             return "foo()";
362         }
363 
364         public String foo(final double d) {
365             return "foo(double)";
366         }
367 
368         public String foo(final int i) {
369             return "foo(int)";
370         }
371 
372         public String foo(final Integer i) {
373             return "foo(Integer)";
374         }
375 
376         public String foo(final Integer i, final String... s) {
377             return "foo(int, String...)";
378         }
379 
380         public String foo(final long l) {
381             return "foo(long)";
382         }
383 
384         public String foo(final long... l) {
385             return "foo(long...)";
386         }
387 
388         public String foo(final Object o) {
389             return "foo(Object)";
390         }
391 
392         public String foo(final Object... s) {
393             return "foo(Object...)";
394         }
395 
396         public String foo(final String s) {
397             return "foo(String)";
398         }
399 
400         public String foo(final String... s) {
401             return "foo(String...)";
402         }
403 
404         public String intIntVarArg(final int intArg, final int... args) {
405             return "int, int...";
406         }
407 
408         public String intLongVarArg(final int intArg, final long... args) {
409             return "int, long...";
410         }
411 
412         public String intStringVarArg(final int intArg, final String... args) {
413             return "int, String...";
414         }
415 
416         public void oneParameter(final String s) {
417             // empty
418         }
419 
420         public String packagePrivateEmptyInterface(final PackagePrivateEmptyInterface... args) {
421             return "PackagePrivateEmptyInterface...";
422         }
423 
424         @SuppressWarnings("unused")
425         private String privateStringStuff() {
426             return "privateStringStuff()";
427         }
428 
429         @SuppressWarnings("unused")
430         private String privateStringStuff(final double d) {
431             return "privateStringStuff(double)";
432         }
433 
434         @SuppressWarnings("unused")
435         private String privateStringStuff(final int i) {
436             return "privateStringStuff(int)";
437         }
438 
439         @SuppressWarnings("unused")
440         private String privateStringStuff(final Integer i) {
441             return "privateStringStuff(Integer)";
442         }
443 
444         @SuppressWarnings("unused")
445         private String privateStringStuff(final Object s) {
446             return "privateStringStuff(Object)";
447         }
448 
449         @SuppressWarnings("unused")
450         private String privateStringStuff(final String s) {
451             return "privateStringStuff(String)";
452         }
453 
454         @SuppressWarnings("unused")
455         private void privateStuff() {
456         }
457 
458         public boolean[] unboxing(final boolean... values) {
459             unboxBooleanArray = true;
460             return values;
461         }
462 
463         public byte[] unboxing(final byte... values) {
464             unboxByteArray = true;
465             return values;
466         }
467 
468         public char[] unboxing(final char... values) {
469             unboxCharArray = true;
470             return values;
471         }
472 
473         public double[] unboxing(final double... values) {
474             unboxDoubleArray = true;
475             return values;
476         }
477 
478         public float[] unboxing(final float... values) {
479             unboxFloatArray = true;
480             return values;
481         }
482 
483         public int[] unboxing(final int... values) {
484             unboxIntArray = true;
485             return values;
486         }
487 
488         public long[] unboxing(final long... values) {
489             unboxLongArray = true;
490             return values;
491         }
492 
493         public short[] unboxing(final short... values) {
494             unboxShortArray = true;
495             return values;
496         }
497 
498         public ImmutablePair<String, Object[]> varOverloadEcho(final Number... args) {
499             return new ImmutablePair<>("Number...", args);
500         }
501 
502         // These varOverloadEcho and varOverloadEchoStatic methods are designed to verify that
503         // not only is the correct overloaded variant invoked, but that the varargs arguments
504         // are also delivered correctly to the method.
505         public ImmutablePair<String, Object[]> varOverloadEcho(final String... args) {
506             return new ImmutablePair<>("String...", args);
507         }
508 
509     }
510 
511     static class TestBeanSubclass extends TestBean {
512     }
513 
514     static class TestBeanWithInterfaces implements PrivateEmptyInterface {
515         public String foo() {
516             return "foo()";
517         }
518     }
519 
520     private static class TestMutable implements Mutable<Object> {
521         @Override
522         public Object getValue() {
523             return null;
524         }
525 
526         @Override
527         public void setValue(final Object value) {
528         }
529     }
530 
531     private static final class TestMutableSubclass extends TestMutable {
532         // empty
533     }
534 
535     private final Map<Class<?>, Class<?>[]> classCache = new HashMap<>();
536 
537     private TestBean testBean;
538 
539     private void expectMatchingAccessibleMethodParameterTypes(final Class<?> cls, final String methodName, final Class<?>[] requestTypes,
540             final Class<?>[] actualTypes) {
541         final Method m = MethodUtils.getMatchingAccessibleMethod(cls, methodName, requestTypes);
542         assertNotNull(m, "could not find any matches for " + methodName + " (" + (requestTypes == null ? null : toString(requestTypes)) + ")");
543         assertArrayEquals(actualTypes, m.getParameterTypes(), toString(m.getParameterTypes()) + " not equals " + toString(actualTypes));
544     }
545 
546     @BeforeEach
547     public void setUp() {
548         testBean = new TestBean();
549         classCache.clear();
550     }
551 
552     private Class<?>[] singletonArray(final Class<?> c) {
553         Class<?>[] result = classCache.get(c);
554         if (result == null) {
555             result = new Class[]{c};
556             classCache.put(c, result);
557         }
558         return result;
559     }
560 
561     @Test
562     void testConstructor() throws Exception {
563         assertNotNull(MethodUtils.class.getConstructor().newInstance());
564     }
565 
566     @Test
567     void testDistance() throws Exception {
568         final Method distanceMethod = MethodUtils.getMatchingMethod(MethodUtils.class, "distance", Class[].class, Class[].class);
569         distanceMethod.setAccessible(true);
570         assertEquals(-1, distanceMethod.invoke(null, new Class[] { String.class }, new Class[] { Date.class }));
571         assertEquals(0, distanceMethod.invoke(null, new Class[] { Date.class }, new Class[] { Date.class }));
572         assertEquals(1, distanceMethod.invoke(null, new Class[] { Integer.class }, new Class[] { ClassUtils.wrapperToPrimitive(Integer.class) }));
573         assertEquals(2, distanceMethod.invoke(null, new Class[] { Integer.class }, new Class[] { Object.class }));
574         distanceMethod.setAccessible(false);
575     }
576 
577     @ParameterizedTest
578     @ValueSource(classes = {TestMutable.class, TestMutableSubclass.class})
579     void testGetAccessibleInterfaceMethod(final Class<?> clazz) throws Exception {
580         final Class<?>[][] p = {ArrayUtils.EMPTY_CLASS_ARRAY, null};
581         for (final Class<?>[] element : p) {
582             final Method method = clazz.getMethod("getValue", element);
583             final Method accessibleMethod = MethodUtils.getAccessibleMethod(method);
584             assertNotSame(accessibleMethod, method);
585             assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
586             final Method accessibleMethod2 = MethodUtils.getAccessibleMethod(clazz, method);
587             assertNotSame(accessibleMethod2, method);
588             assertSame(Mutable.class, accessibleMethod2.getDeclaringClass());
589         }
590     }
591 
592     @ParameterizedTest
593     @ValueSource(classes = {TestMutable.class, TestMutableSubclass.class})
594     void testGetAccessibleInterfaceMethodFromDescription(final Class<?> clazz) {
595         final Class<?>[][] p = { ArrayUtils.EMPTY_CLASS_ARRAY, null };
596         for (final Class<?>[] element : p) {
597             final Method accessibleMethod = MethodUtils.getAccessibleMethod(clazz, "getValue", element);
598             assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
599         }
600     }
601 
602     @Test
603     void testGetAccessibleMethodInaccessible() throws Exception {
604         assertNull(MethodUtils.getAccessibleMethod(TestBean.class.getDeclaredMethod("privateStuff")));
605         assertNull(MethodUtils.getAccessibleMethod(TestBean.class, TestBean.class.getDeclaredMethod("privateStuff")));
606         assertNull(MethodUtils.getAccessibleMethod(TestBeanSubclass.class, TestBean.class.getDeclaredMethod("privateStuff")));
607     }
608 
609     @Test
610     void testGetAccessibleMethodPrivateInterface() throws Exception {
611         final Method expected = TestBeanWithInterfaces.class.getMethod("foo");
612         assertNotNull(expected);
613         final Method actual = MethodUtils.getAccessibleMethod(TestBeanWithInterfaces.class, "foo");
614         assertNull(actual);
615     }
616 
617     @Test
618     void testGetAccessibleMethodPublicSub() throws Exception {
619         // PackageBean class is package-private
620         final int modifiers = PackageBean.class.getModifiers();
621         assertFalse(Modifier.isPrivate(modifiers));
622         assertFalse(Modifier.isProtected(modifiers));
623         assertFalse(Modifier.isPublic(modifiers));
624         // make sure that bean does what it should: compile
625         new PublicSubBean().setBar("");
626         // make sure that bean does what it should
627         final PublicSubBean bean = new PublicSubBean();
628         assertEquals(bean.getFoo(), "This is foo", "Start value (foo)");
629         assertEquals(bean.getBar(), "This is bar", "Start value (bar)");
630         bean.setFoo("new foo");
631         bean.setBar("new bar");
632         assertEquals(bean.getFoo(), "new foo", "Set value (foo)");
633         assertEquals(bean.getBar(), "new bar", "Set value (bar)");
634         // see if we can access public methods in a default access superclass
635         // from a public access subclass instance
636         MethodUtils.invokeExactMethod(bean, "setFoo", "alpha");
637         assertEquals(bean.getFoo(), "alpha", "Set value (foo:2)");
638         MethodUtils.invokeExactMethod(bean, "setBar", "beta");
639         assertEquals(bean.getBar(), "beta", "Set value (bar:2)");
640         // PublicSubBean.setFoo(String)
641         Method method = MethodUtils.getAccessibleMethod(PublicSubBean.class, "setFoo", String.class);
642         assertNotNull(method, "getAccessibleMethod() setFoo is Null");
643         method.invoke(bean, "1111");
644         assertEquals("1111", bean.getFoo(), "Set value (foo:3)");
645         // PublicSubBean.setBar(String)
646         method = MethodUtils.getAccessibleMethod(PublicSubBean.class, "setBar", String.class);
647         assertNotNull(method, "getAccessibleMethod() setBar is Null");
648         method.invoke(bean, "2222");
649         assertEquals("2222", bean.getBar(), "Set value (bar:3)");
650     }
651 
652     @Test
653     void testGetAccessibleMethodPublicSubOtherPackage() throws Exception {
654         // PackageBeanOtherPackage class is package-private
655         final int modifiers = Class.forName("org.apache.commons.lang3.reflect.testbed.PackageBeanOtherPackage").getModifiers();
656         assertFalse(Modifier.isPrivate(modifiers));
657         assertFalse(Modifier.isProtected(modifiers));
658         assertFalse(Modifier.isPublic(modifiers));
659         // make sure that bean does what it should: compile
660         new PublicSubBeanOtherPackage().setBar("");
661         // make sure that bean does what it should
662         final PublicSubBeanOtherPackage bean = new PublicSubBeanOtherPackage();
663         assertEquals(bean.getFoo(), "This is foo", "Start value (foo)");
664         assertEquals(bean.getBar(), "This is bar", "Start value (bar)");
665         bean.setFoo("new foo");
666         bean.setBar("new bar");
667         assertEquals(bean.getFoo(), "new foo", "Set value (foo)");
668         assertEquals(bean.getBar(), "new bar", "Set value (bar)");
669         // see if we can access public methods in a default access superclass
670         // from a public access subclass instance
671         MethodUtils.invokeExactMethod(bean, "setFoo", "alpha");
672         assertEquals(bean.getFoo(), "alpha", "Set value (foo:2)");
673         MethodUtils.invokeExactMethod(bean, "setBar", "beta");
674         assertEquals(bean.getBar(), "beta", "Set value (bar:2)");
675         // PublicSubBean.setFoo(String)
676         Method method = MethodUtils.getAccessibleMethod(PublicSubBeanOtherPackage.class, "setFoo", String.class);
677         assertNotNull(method, "getAccessibleMethod() setFoo is Null");
678         method.invoke(bean, "1111");
679         assertEquals("1111", bean.getFoo(), "Set value (foo:3)");
680         // PublicSubBean.setBar(String)
681         method = MethodUtils.getAccessibleMethod(PublicSubBeanOtherPackage.class, "setBar", String.class);
682         assertNotNull(method, "getAccessibleMethod() setBar is Null");
683         method.invoke(bean, "2222");
684         assertEquals("2222", bean.getBar(), "Set value (bar:3)");
685     }
686 
687     @Test
688     void testGetAccessiblePublicMethod() throws Exception {
689         assertSame(MutableObject.class,
690                 MethodUtils.getAccessibleMethod(MutableObject.class.getMethod("getValue", ArrayUtils.EMPTY_CLASS_ARRAY)).getDeclaringClass());
691         assertSame(MutableObject.class, MethodUtils
692                 .getAccessibleMethod(MutableObject.class, MutableObject.class.getMethod("getValue", ArrayUtils.EMPTY_CLASS_ARRAY)).getDeclaringClass());
693     }
694 
695     @Test
696     void testGetAccessiblePublicMethodFromDescription() {
697         assertSame(MutableObject.class, MethodUtils.getAccessibleMethod(MutableObject.class, "getValue", ArrayUtils.EMPTY_CLASS_ARRAY).getDeclaringClass());
698     }
699 
700     @Test
701     void testGetAnnotationIllegalArgumentException1() {
702         assertNullPointerException(
703                 () -> MethodUtils.getAnnotation(FieldUtilsTest.class.getDeclaredMethods()[0], null, true, true));
704     }
705 
706     @Test
707     void testGetAnnotationIllegalArgumentException2() {
708         assertNullPointerException(() -> MethodUtils.getAnnotation(null, Annotated.class, true, true));
709     }
710 
711     @Test
712     void testGetAnnotationIllegalArgumentException3() {
713         assertNullPointerException(() -> MethodUtils.getAnnotation(null, null, true, true));
714     }
715 
716     @Test
717     void testGetAnnotationNotSearchSupersAndNotIgnoreAccess() throws NoSuchMethodException {
718         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"),
719                 Annotated.class, false, false));
720         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class,
721                 false, false));
722         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"),
723                 Annotated.class, false, false));
724         assertNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"),
725                 Annotated.class, false, false));
726         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"),
727                 Annotated.class, false, false));
728     }
729 
730     @Test
731     void testGetAnnotationNotSearchSupersButIgnoreAccess() throws NoSuchMethodException {
732         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"),
733                 Annotated.class, false, true));
734         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class,
735                 false, true));
736         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"),
737                 Annotated.class, false, true));
738         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"),
739                 Annotated.class, false, true));
740         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"),
741                 Annotated.class, false, true));
742     }
743 
744     @Test
745     void testGetAnnotationSearchSupersAndIgnoreAccess() throws NoSuchMethodException {
746         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"),
747                 Annotated.class, true, true));
748         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class,
749                 true, true));
750         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"),
751                 Annotated.class, true, true));
752         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"),
753                 Annotated.class, true, true));
754         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"),
755                 Annotated.class, true, true));
756 
757         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentNotAnnotatedMethod", String.class),
758                 Annotated.class, true, true));
759         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentProtectedAnnotatedMethod", String.class),
760                 Annotated.class, true, true));
761         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getDeclaredMethod("privateAnnotatedMethod", String.class),
762                 Annotated.class, true, true));
763         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("publicAnnotatedMethod", String.class),
764                 Annotated.class, true, true));
765     }
766 
767     @Test
768     void testGetAnnotationSearchSupersButNotIgnoreAccess() throws NoSuchMethodException {
769         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"),
770                 Annotated.class, true, false));
771         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class,
772                 true, false));
773         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"),
774                 Annotated.class, true, false));
775         assertNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"),
776                 Annotated.class, true, false));
777         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"),
778                 Annotated.class, true, false));
779 
780         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentNotAnnotatedMethod", String.class),
781                 Annotated.class, true, false));
782         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentProtectedAnnotatedMethod", String.class),
783                 Annotated.class, true, false));
784         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getDeclaredMethod("privateAnnotatedMethod", String.class),
785                 Annotated.class, true, false));
786         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("publicAnnotatedMethod", String.class),
787                 Annotated.class, true, false));
788     }
789 
790     @Test
791     void testGetMatchingAccessibleMethod() {
792         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", ArrayUtils.EMPTY_CLASS_ARRAY, ArrayUtils.EMPTY_CLASS_ARRAY);
793         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", null, ArrayUtils.EMPTY_CLASS_ARRAY);
794         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(String.class), singletonArray(String.class));
795         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Object.class), singletonArray(Object.class));
796         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Boolean.class), singletonArray(Object.class));
797         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Byte.class), singletonArray(Integer.TYPE));
798         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Byte.TYPE), singletonArray(Integer.TYPE));
799         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Short.class), singletonArray(Integer.TYPE));
800         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Short.TYPE), singletonArray(Integer.TYPE));
801         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Character.class), singletonArray(Integer.TYPE));
802         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Character.TYPE), singletonArray(Integer.TYPE));
803         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Integer.class), singletonArray(Integer.class));
804         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Integer.TYPE), singletonArray(Integer.TYPE));
805         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Long.class), singletonArray(Long.TYPE));
806         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Long.TYPE), singletonArray(Long.TYPE));
807         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Float.class), singletonArray(Double.TYPE));
808         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Float.TYPE), singletonArray(Double.TYPE));
809         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.class), singletonArray(Double.TYPE));
810         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.TYPE), singletonArray(Double.TYPE));
811         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.TYPE), singletonArray(Double.TYPE));
812         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", new Class[] { String.class, String.class }, new Class[] { String[].class });
813         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", new Class[] { Integer.TYPE, String.class, String.class },
814                 new Class[] { Integer.class, String[].class });
815         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne", singletonArray(ParentObject.class), singletonArray(ParentObject.class));
816         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne", singletonArray(ChildObject.class), singletonArray(ParentObject.class));
817         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo", singletonArray(ParentObject.class),
818                 singletonArray(GrandParentObject.class));
819         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo", singletonArray(ChildObject.class), singletonArray(PackagePrivateEmptyInterface.class));
820         // LANG-1757
821         expectMatchingAccessibleMethodParameterTypes(Files.class, "exists", singletonArray(Path.class), new Class[] { Path.class, LinkOption[].class });
822     }
823 
824     @Test
825     void testGetMatchingMethod() throws NoSuchMethodException {
826         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod"), GetMatchingMethodClass.class.getMethod("testMethod"));
827         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", Long.TYPE),
828                 GetMatchingMethodClass.class.getMethod("testMethod", Long.TYPE));
829         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", Long.class),
830                 GetMatchingMethodClass.class.getMethod("testMethod", Long.class));
831         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", (Class<?>) null),
832                 GetMatchingMethodClass.class.getMethod("testMethod", Long.class));
833         assertThrows(IllegalStateException.class, () -> MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod2", (Class<?>) null));
834         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.TYPE, Long.class),
835                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.TYPE, Long.class));
836         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.class, Long.TYPE),
837                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.class, Long.TYPE));
838         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", null, Long.TYPE),
839                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.class, Long.TYPE));
840         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.TYPE, null),
841                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.TYPE, Long.class));
842         assertThrows(IllegalStateException.class, () -> MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod4", null, null));
843         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodImpl.class, "testMethod5", RuntimeException.class),
844                 GetMatchingMethodImpl.class.getMethod("testMethod5", Exception.class));
845         assertEquals(GetMatchingMethodImpl.class.getMethod("testMethod6"), MethodUtils.getMatchingMethod(GetMatchingMethodImpl.class, "testMethod6"));
846         assertNullPointerException(() -> MethodUtils.getMatchingMethod(null, "testMethod5", RuntimeException.class));
847         Method testMethod6 = MethodUtils.getMatchingMethod(ConcreteGetMatchingMethod2.class, "testMethod6");
848         assertNotNull(testMethod6);
849         assertEquals(AbstractGetMatchingMethod2.class, testMethod6.getDeclaringClass());
850         testMethod6 = MethodUtils.getMatchingMethod(ConcreteGetMatchingMethod22.class, "testMethod6");
851         assertNotNull(testMethod6);
852         assertEquals(ConcreteGetMatchingMethod22.class, testMethod6.getDeclaringClass());
853     }
854 
855     @Test
856     void testGetMethodObject() throws Exception {
857         assertEquals(MutableObject.class.getMethod("getValue", ArrayUtils.EMPTY_CLASS_ARRAY),
858                 MethodUtils.getMethodObject(MutableObject.class, "getValue", ArrayUtils.EMPTY_CLASS_ARRAY));
859         assertNull(MethodUtils.getMethodObject(MutableObject.class, "does not exist, at all", ArrayUtils.EMPTY_CLASS_ARRAY));
860         assertNull(MethodUtils.getMethodObject(null, "does not exist, at all", ArrayUtils.EMPTY_CLASS_ARRAY));
861         assertNull(MethodUtils.getMethodObject(null, null, ArrayUtils.EMPTY_CLASS_ARRAY));
862         assertNull(MethodUtils.getMethodObject(MutableObject.class, null, ArrayUtils.EMPTY_CLASS_ARRAY));
863         // 0 args
864         assertNull(MethodUtils.getMethodObject(MutableObject.class, "getValue", new Class[] { null }));
865         // 1 args
866         assertNull(MethodUtils.getMethodObject(MutableObject.class, "equals", new Class[] { null }));
867         assertNull(MethodUtils.getMethodObject(MutableObject.class, "equals", new Class[] { String.class, null, String.class }));
868     }
869 
870     /**
871      * Tests a {@code public} method.
872      */
873     @Test
874     @Annotated
875     public void testGetMethodsListWithAnnotation() throws NoSuchMethodException {
876         assertEquals(0, MethodUtils.getMethodsListWithAnnotation(Object.class, Annotated.class).size());
877 
878         final List<Method> methodWithAnnotation = MethodUtils.getMethodsListWithAnnotation(MethodUtilsTest.class, Annotated.class);
879         assertEquals(2, methodWithAnnotation.size());
880         assertTrue(methodWithAnnotation.contains(MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation")));
881         assertTrue(methodWithAnnotation.contains(MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")));
882     }
883 
884     @Test
885     void testGetMethodsListWithAnnotationNullPointerException1() {
886         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(FieldUtilsTest.class, null));
887     }
888 
889     @Test
890     void testGetMethodsListWithAnnotationNullPointerException2() {
891         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(null, Annotated.class));
892     }
893 
894     @Test
895     void testGetMethodsListWithAnnotationNullPointerException3() {
896         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(null, null));
897     }
898 
899     @Test
900     @Annotated
901     public void testGetMethodsWithAnnotation() throws NoSuchMethodException {
902         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class));
903 
904         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(MethodUtilsTest.class, Annotated.class);
905         assertEquals(2, methodsWithAnnotation.length);
906         assertTrue(ArrayUtils.contains(methodsWithAnnotation, MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation")));
907         assertTrue(ArrayUtils.contains(methodsWithAnnotation, MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")));
908     }
909 
910     @Test
911     void testGetMethodsWithAnnotationIllegalArgumentException1() {
912         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(FieldUtilsTest.class, null));
913     }
914 
915     @Test
916     void testGetMethodsWithAnnotationIllegalArgumentException2() {
917         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(null, Annotated.class));
918     }
919 
920     @Test
921     void testGetMethodsWithAnnotationIllegalArgumentException3() {
922         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(null, null));
923     }
924 
925     @Test
926     void testGetMethodsWithAnnotationNotSearchSupersAndNotIgnoreAccess() {
927         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, false, false));
928         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, false, false);
929         assertEquals(1, methodsWithAnnotation.length);
930         assertEquals("PublicChild.publicAnnotatedMethod",
931                 methodsWithAnnotation[0].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[0].getName());
932     }
933 
934     @Test
935     void testGetMethodsWithAnnotationNotSearchSupersButIgnoreAccess() {
936         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, false, true));
937         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, false, true);
938         assertEquals(2, methodsWithAnnotation.length);
939         assertEquals("PublicChild", methodsWithAnnotation[0].getDeclaringClass().getSimpleName());
940         assertEquals("PublicChild", methodsWithAnnotation[1].getDeclaringClass().getSimpleName());
941         assertTrue(methodsWithAnnotation[0].getName().endsWith("AnnotatedMethod"));
942         assertTrue(methodsWithAnnotation[1].getName().endsWith("AnnotatedMethod"));
943     }
944 
945     @Test
946     void testGetMethodsWithAnnotationSearchSupersAndIgnoreAccess() {
947         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, true, true));
948         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, true, true);
949         assertEquals(4, methodsWithAnnotation.length);
950         assertEquals("PublicChild", methodsWithAnnotation[0].getDeclaringClass().getSimpleName());
951         assertEquals("PublicChild", methodsWithAnnotation[1].getDeclaringClass().getSimpleName());
952         assertTrue(methodsWithAnnotation[0].getName().endsWith("AnnotatedMethod"));
953         assertTrue(methodsWithAnnotation[1].getName().endsWith("AnnotatedMethod"));
954         assertEquals("Foo.doIt", methodsWithAnnotation[2].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[2].getName());
955         assertEquals("Parent.parentProtectedAnnotatedMethod",
956                 methodsWithAnnotation[3].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[3].getName());
957     }
958 
959     @Test
960     void testGetMethodsWithAnnotationSearchSupersButNotIgnoreAccess() {
961         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, true, false));
962         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, true, false);
963         assertEquals(2, methodsWithAnnotation.length);
964         assertEquals("PublicChild.publicAnnotatedMethod",
965                 methodsWithAnnotation[0].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[0].getName());
966         assertEquals("Foo.doIt", methodsWithAnnotation[1].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[1].getName());
967     }
968 
969     @Test
970     void testGetOverrideHierarchyExcludingInterfaces() {
971         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
972         final Iterator<MethodDescriptor> expected =
973                 Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
974                         new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]))
975                         .iterator();
976         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.EXCLUDE)) {
977             assertTrue(expected.hasNext());
978             final MethodDescriptor md = expected.next();
979             assertEquals(md.declaringClass, m.getDeclaringClass());
980             assertEquals(md.name, m.getName());
981             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
982             for (int i = 0; i < md.parameterTypes.length; i++) {
983                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
984             }
985         }
986         assertFalse(expected.hasNext());
987     }
988 
989     @Test
990     void testGetOverrideHierarchyIncludingInterfaces() {
991         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
992         final Iterator<MethodDescriptor> expected =
993                 Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
994                         new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]),
995                         new MethodDescriptor(GenericConsumer.class, "consume", GenericConsumer.class.getTypeParameters()[0]))
996                         .iterator();
997         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.INCLUDE)) {
998             assertTrue(expected.hasNext());
999             final MethodDescriptor md = expected.next();
1000             assertEquals(md.declaringClass, m.getDeclaringClass());
1001             assertEquals(md.name, m.getName());
1002             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
1003             for (int i = 0; i < md.parameterTypes.length; i++) {
1004                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
1005             }
1006         }
1007         assertFalse(expected.hasNext());
1008     }
1009 
1010     @Test
1011     void testInvokeExactMethod() throws Exception {
1012         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1013         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo"));
1014         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", (Object[]) null));
1015         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", null, null));
1016         assertEquals("foo(String)", MethodUtils.invokeExactMethod(testBean, "foo", ""));
1017         assertEquals("foo(Object)", MethodUtils.invokeExactMethod(testBean, "foo", new Object()));
1018         assertEquals("foo(Integer)", MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.INTEGER_ONE));
1019         assertEquals("foo(double)", MethodUtils.invokeExactMethod(testBean, "foo", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1020         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.BYTE_ONE));
1021         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.LONG_ONE));
1022         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", Boolean.TRUE));
1023         assertThrows(NullPointerException.class, () -> MethodUtils.invokeExactMethod(null, "foo", NumberUtils.BYTE_ONE));
1024         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, null, NumberUtils.BYTE_ONE));
1025         assertThrows(NullPointerException.class,
1026                 () -> MethodUtils.invokeExactMethod(null, "foo", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1027         assertThrows(NoSuchMethodException.class,
1028                 () -> MethodUtils.invokeExactMethod(testBean, null, new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1029     }
1030 
1031     @Test
1032     void testInvokeExactStaticMethod() throws Exception {
1033         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1034         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", (Object[]) null));
1035         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", null, null));
1036         assertEquals("bar(String)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", ""));
1037         assertEquals("bar(Object)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", new Object()));
1038         assertEquals("bar(Integer)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE));
1039         assertEquals("bar(double)",
1040                 MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1041         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.BYTE_ONE));
1042         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.LONG_ONE));
1043         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", Boolean.TRUE));
1044     }
1045 
1046     @Test
1047     void testInvokeJavaVarArgsOverloadingResolution() throws Exception {
1048         // Primitive wrappers
1049         assertEquals("Byte...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (byte) 1, (byte) 2));
1050         assertEquals("Short...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (short) 1, (short) 2));
1051         assertEquals("Integer...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 2));
1052         assertEquals("Long...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1L, 2L));
1053         assertEquals("Float...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1f, 2f));
1054         assertEquals("Double...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1d, 2d));
1055         assertEquals("Boolean...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", true, false));
1056         // Number
1057         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 1.1));
1058         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 1L));
1059         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1d, 1f));
1060         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (short) 1, (byte) 1));
1061         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", ArrayUtils.EMPTY_OBJECT_ARRAY));
1062         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1063         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", (Object[]) ArrayUtils.EMPTY_INTEGER_OBJECT_ARRAY));
1064         // Object
1065         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, "s"));
1066         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, true));
1067         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1.1, true));
1068         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'c', true));
1069         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 'c'));
1070         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'c', "s"));
1071         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", ArrayUtils.EMPTY_OBJECT_ARRAY));
1072         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1073         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (Object[]) ArrayUtils.EMPTY_INTEGER_OBJECT_ARRAY));
1074         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload"));
1075         // Other
1076         assertEquals("String...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", "a", "b"));
1077         assertEquals("Character...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'a', 'b'));
1078     }
1079 
1080     @Test
1081     void testInvokeMethod() throws Exception {
1082         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1083         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo"));
1084         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", (Object[]) null));
1085         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", null, null));
1086         assertEquals("foo(String)", MethodUtils.invokeMethod(testBean, "foo", ""));
1087         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo", new Object()));
1088         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo", Boolean.TRUE));
1089         assertEquals("foo(Integer)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.INTEGER_ONE));
1090         assertEquals("foo(int)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.BYTE_ONE));
1091         assertEquals("foo(long)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.LONG_ONE));
1092         assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.DOUBLE_ONE));
1093         assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo", "a", "b", "c"));
1094         assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo", "a", "b", "c"));
1095         assertEquals("foo(int, String...)", MethodUtils.invokeMethod(testBean, "foo", 5, "a", "b", "c"));
1096         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", 1L, 2L));
1097         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", 1, 2));
1098         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (byte) 1, (byte) 2)); // widen
1099         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (short) 1, (short) 2)); // widen
1100         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (char) 1, (char) 2)); // widen
1101         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y"));
1102         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", 17, 23, 42));
1103         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y"));
1104         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", 17, 23, 42));
1105         assertNullPointerException(() -> MethodUtils.invokeMethod(null, "foo", 1, 2));
1106         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, null, 1, 2));
1107         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(new Object(), "nonExistent", new Object[] { "val" }, new Class<?>[] { null }));
1108     }
1109 
1110     @Test
1111     void testInvokeMethod_VarArgsWithNullValues() throws Exception {
1112         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", "a", null, "c"));
1113         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", "a", "b", null));
1114         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", new String[] { "a" }, new Class<?>[] { String.class }));
1115         assertThrows(NoSuchMethodException.class,
1116                 () -> assertEquals("String...", MethodUtils.invokeMethod(testBean, "doesn't exist", new String[] { "a" }, new Class<?>[] { null })));
1117     }
1118 
1119     @Test
1120     void testInvokeMethod1PlusVarArgs() throws Exception {
1121         // intStringVarArg
1122         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1));
1123         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s"));
1124         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s1", "s2"));
1125         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s1", 5));
1126         // intLongVarArg
1127         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1));
1128         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, 2L));
1129         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, 2L, 3L));
1130         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, "s1", 5));
1131         // intIntVarArg
1132         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1));
1133         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1, 2));
1134         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1, 2, 3));
1135         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, "s1", 5));
1136     }
1137 
1138     @Test
1139     void testInvokeMethodForceAccessNoArgs() throws Exception {
1140         assertEquals("privateStringStuff()", MethodUtils.invokeMethod(testBean, true, "privateStringStuff"));
1141     }
1142 
1143     @Test
1144     void testInvokeMethodForceAccessWithArgs() throws Exception {
1145         assertEquals("privateStringStuff(Integer)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", 5));
1146         assertEquals("privateStringStuff(double)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", 5.0d));
1147         assertEquals("privateStringStuff(String)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", "Hi There"));
1148         assertEquals("privateStringStuff(Object)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", new Date()));
1149         assertNullPointerException(() -> MethodUtils.invokeMethod(null, true, "privateStringStuff", "Hi There"));
1150         assertNullPointerException(() -> MethodUtils.invokeMethod(testBean, true, null, "Hi There"));
1151     }
1152 
1153     @Test
1154     void testInvokeMethodVarArgsNotUniqueResolvable() throws Exception {
1155         assertEquals("Boolean...", MethodUtils.invokeMethod(testBean, "varOverload", new Object[] { null }));
1156         assertEquals("Object...", MethodUtils.invokeMethod(testBean, "varOverload", (Object[]) null));
1157     }
1158 
1159     @Test
1160     void testInvokeMethodVarArgsOfInterface() throws Exception {
1161         // packagePrivateEmptyInterface
1162         assertEquals("PackagePrivateEmptyInterface...", MethodUtils.invokeMethod(testBean, "packagePrivateEmptyInterface",
1163                 new PublicImpl1OfPackagePrivateEmptyInterface(), new PublicImpl2OfPackagePrivateEmptyInterface()));
1164         assertEquals("PackagePrivateEmptyInterface...", MethodUtils.invokeMethod(testBean, "packagePrivateEmptyInterface", new PackagePrivateEmptyInterface() {
1165             // empty
1166         }, new PackagePrivateEmptyInterface() {
1167             // empty
1168         }));
1169     }
1170 
1171     @Test
1172     void testInvokeMethodVarArgsUnboxingBooleanArray() throws Exception {
1173         final TestBean testBean = new TestBean();
1174         final boolean[] actual = (boolean[]) MethodUtils.invokeMethod(testBean, "unboxing", Boolean.TRUE, Boolean.FALSE);
1175         assertArrayEquals(new boolean[] { true, false }, actual);
1176         assertTrue(testBean.unboxBooleanArray);
1177     }
1178 
1179     @Test
1180     void testInvokeMethodVarArgsUnboxingByteArray() throws Exception {
1181         final TestBean testBean = new TestBean();
1182         final byte[] actual = (byte[]) MethodUtils.invokeMethod(testBean, "unboxing", Byte.valueOf((byte) 1), Byte.valueOf((byte) 2));
1183         assertArrayEquals(new byte[] { 1, 2 }, actual);
1184         assertTrue(testBean.unboxByteArray);
1185     }
1186 
1187     @Test
1188     void testInvokeMethodVarArgsUnboxingCharArray() throws Exception {
1189         final TestBean testBean = new TestBean();
1190         final char[] actual = (char[]) MethodUtils.invokeMethod(testBean, "unboxing", Character.valueOf((char) 1), Character.valueOf((char) 2));
1191         assertArrayEquals(new char[] { 1, 2 }, actual);
1192         assertTrue(testBean.unboxCharArray);
1193     }
1194 
1195     @Test
1196     void testInvokeMethodVarArgsUnboxingDoubleArray() throws Exception {
1197         final TestBean testBean = new TestBean();
1198         final double[] actual = (double[]) MethodUtils.invokeMethod(testBean, "unboxing", Double.valueOf(1), Double.valueOf(2));
1199         assertArrayEquals(new double[] { 1, 2 }, actual);
1200         assertTrue(testBean.unboxDoubleArray);
1201     }
1202 
1203     @Test
1204     void testInvokeMethodVarArgsUnboxingFloatArray() throws Exception {
1205         final TestBean testBean = new TestBean();
1206         final float[] actual = (float[]) MethodUtils.invokeMethod(testBean, "unboxing", Float.valueOf(1), Float.valueOf(2));
1207         assertArrayEquals(new float[] { 1, 2 }, actual);
1208         assertTrue(testBean.unboxFloatArray);
1209     }
1210 
1211     @Test
1212     void testInvokeMethodVarArgsUnboxingIntArray() throws Exception {
1213         final TestBean testBean = new TestBean();
1214         final int[] actual = (int[]) MethodUtils.invokeMethod(testBean, "unboxing", Integer.valueOf(1), Integer.valueOf(2));
1215         assertArrayEquals(new int[] { 1, 2 }, actual);
1216         assertTrue(testBean.unboxIntArray);
1217     }
1218 
1219     @Test
1220     void testInvokeMethodVarArgsUnboxingLongArray() throws Exception {
1221         final TestBean testBean = new TestBean();
1222         final long[] actual = (long[]) MethodUtils.invokeMethod(testBean, "unboxing", Long.valueOf(1), Long.valueOf(2));
1223         assertArrayEquals(new long[] { 1, 2 }, actual);
1224         assertTrue(testBean.unboxLongArray);
1225     }
1226 
1227     @Test
1228     void testInvokeMethodVarArgsUnboxingShortArray() throws Exception {
1229         final TestBean testBean = new TestBean();
1230         final short[] actual = (short[]) MethodUtils.invokeMethod(testBean, "unboxing", Short.valueOf((short) 1), Short.valueOf((short) 2));
1231         assertArrayEquals(new short[] { 1, 2 }, actual);
1232         assertTrue(testBean.unboxShortArray);
1233     }
1234 
1235     @Test
1236     void testInvokeStaticMethod() throws Exception {
1237         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar"));
1238         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1239         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (Object[]) null));
1240         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", null, null));
1241         assertEquals("bar(String)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", ""));
1242         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", new Object()));
1243         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", Boolean.TRUE));
1244         assertEquals("bar(Integer)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE));
1245         assertEquals("bar(int)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.BYTE_ONE));
1246         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.BYTE_ONE));
1247         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.SHORT_ONE));
1248         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.INTEGER_ONE));
1249         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", 'a'));
1250         assertEquals("bar(double)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
1251         assertEquals("bar(String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", "a", "b"));
1252         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", 1L, 2L));
1253         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (byte) 1, (byte) 2)); // widen
1254         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (short) 1, (short) 2)); // widen
1255         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", 1, 2)); // widen
1256         assertEquals("bar(Integer, String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE, "a", "b"));
1257         // You cannot widen a Short to an Integer in Java source, but you can a short to an int but this API declares an Integer, not an int.
1258         assertThrows(NoSuchMethodException.class,
1259                 () -> assertEquals("bar(Integer, String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.SHORT_ONE, "a", "b"))); // widen
1260         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }),
1261                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", "x", "y"));
1262         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }),
1263                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", 17, 23, 42));
1264         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }),
1265                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", "x", "y"));
1266         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }),
1267                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", 17, 23, 42));
1268         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeStaticMethod(TestBean.class, "does_not_exist"));
1269     }
1270 
1271     @Test
1272     void testInvokeStaticMethod1PlusVarArgs() throws Exception {
1273         // staticIntStringVarArg
1274         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1));
1275         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s"));
1276         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s1", "s2"));
1277         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s1", 5));
1278         // staticIntLongVarArg
1279         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1));
1280         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, 2L));
1281         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, 2L, 3L));
1282         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, "s1", 5));
1283         // staticIntIntVarArg
1284         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1));
1285         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, 2));
1286         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, 2, 3));
1287         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, "s1", 5));
1288     }
1289 
1290     @Test
1291     void testInvokeStaticMethodVarArgsOfInterface() throws Exception {
1292         // staticPackagePrivateEmptyInterface
1293         assertEquals("static PackagePrivateEmptyInterface...", MethodUtils.invokeStaticMethod(TestBean.class, "staticPackagePrivateEmptyInterface",
1294                 new PublicImpl1OfPackagePrivateEmptyInterface(), new PublicImpl2OfPackagePrivateEmptyInterface()));
1295         assertEquals("static PackagePrivateEmptyInterface...",
1296                 MethodUtils.invokeStaticMethod(TestBean.class, "staticPackagePrivateEmptyInterface", new PackagePrivateEmptyInterface() {
1297                     // empty
1298                 }, new PackagePrivateEmptyInterface() {
1299                     // empty
1300                 }));
1301     }
1302 
1303     @Test
1304     void testNullArgument() {
1305         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "oneParameter", singletonArray(null), singletonArray(String.class));
1306     }
1307 
1308     @Test
1309     void testVarargsOverloadingResolution() {
1310         // This code is not a test of MethodUtils.
1311         // Rather it makes explicit the behavior of the Java specification for
1312         // various cases of overload resolution.
1313         assertEquals("Byte...", TestBean.varOverload((byte) 1, (byte) 2));
1314         assertEquals("Short...", TestBean.varOverload((short) 1, (short) 2));
1315         assertEquals("Integer...", TestBean.varOverload(1, 2));
1316         assertEquals("Long...", TestBean.varOverload(1L, 2L));
1317         assertEquals("Float...", TestBean.varOverload(1f, 2f));
1318         assertEquals("Double...", TestBean.varOverload(1d, 2d));
1319         assertEquals("Character...", TestBean.varOverload('a', 'b'));
1320         assertEquals("String...", TestBean.varOverload("a", "b"));
1321         assertEquals("Boolean...", TestBean.varOverload(true, false));
1322         assertEquals("Object...", TestBean.varOverload(1, "s"));
1323         assertEquals("Object...", TestBean.varOverload(1, true));
1324         assertEquals("Object...", TestBean.varOverload(1.1, true));
1325         assertEquals("Object...", TestBean.varOverload('c', true));
1326         assertEquals("Number...", TestBean.varOverload(1, 1.1));
1327         assertEquals("Number...", TestBean.varOverload(1, 1L));
1328         assertEquals("Number...", TestBean.varOverload(1d, 1f));
1329         assertEquals("Number...", TestBean.varOverload((short) 1, (byte) 1));
1330         assertEquals("Object...", TestBean.varOverload(1, 'c'));
1331         assertEquals("Object...", TestBean.varOverload('c', "s"));
1332     }
1333 
1334     private String toString(final Class<?>[] c) {
1335         return Arrays.asList(c).toString();
1336     }
1337 }