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(() -> MethodUtils.getAnnotation(FieldUtilsTest.class.getDeclaredMethods()[0], null, true, true));
703     }
704 
705     @Test
706     void testGetAnnotationIllegalArgumentException2() {
707         assertNullPointerException(() -> MethodUtils.getAnnotation(null, Annotated.class, true, true));
708     }
709 
710     @Test
711     void testGetAnnotationIllegalArgumentException3() {
712         assertNullPointerException(() -> MethodUtils.getAnnotation(null, null, true, true));
713     }
714 
715     @Test
716     void testGetAnnotationNotSearchSupersAndNotIgnoreAccess() throws NoSuchMethodException {
717         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"), Annotated.class, false, false));
718         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class, false, false));
719         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"), Annotated.class, false, false));
720         assertNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"), Annotated.class, false, false));
721         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"), Annotated.class, false, false));
722     }
723 
724     @Test
725     void testGetAnnotationNotSearchSupersButIgnoreAccess() throws NoSuchMethodException {
726         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"), Annotated.class, false, true));
727         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class, false, true));
728         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"), Annotated.class, false, true));
729         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"), Annotated.class, false, true));
730         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"), Annotated.class, false, true));
731     }
732 
733     @Test
734     void testGetAnnotationSearchSupersAndIgnoreAccess() throws NoSuchMethodException {
735         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"), Annotated.class, true, true));
736         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class, true, true));
737         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"), Annotated.class, true, true));
738         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"), Annotated.class, true, true));
739         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"), Annotated.class, true, true));
740         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentNotAnnotatedMethod", String.class), Annotated.class, true, true));
741         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentProtectedAnnotatedMethod", String.class), Annotated.class, true,
742                 true));
743         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getDeclaredMethod("privateAnnotatedMethod", String.class), Annotated.class, true,
744                 true));
745         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("publicAnnotatedMethod", String.class), Annotated.class, true, true));
746     }
747 
748     @Test
749     void testGetAnnotationSearchSupersButNotIgnoreAccess() throws NoSuchMethodException {
750         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentNotAnnotatedMethod"), Annotated.class, true, false));
751         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("doIt"), Annotated.class, true, false));
752         assertNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("parentProtectedAnnotatedMethod"), Annotated.class, true, false));
753         assertNull(MethodUtils.getAnnotation(PublicChild.class.getDeclaredMethod("privateAnnotatedMethod"), Annotated.class, true, false));
754         assertNotNull(MethodUtils.getAnnotation(PublicChild.class.getMethod("publicAnnotatedMethod"), Annotated.class, true, false));
755         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentNotAnnotatedMethod", String.class), Annotated.class, true, false));
756         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("parentProtectedAnnotatedMethod", String.class), Annotated.class, true,
757                 false));
758         assertNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getDeclaredMethod("privateAnnotatedMethod", String.class), Annotated.class, true,
759                 false));
760         assertNotNull(MethodUtils.getAnnotation(StringParameterizedChild.class.getMethod("publicAnnotatedMethod", String.class), Annotated.class, true, false));
761     }
762 
763     @Test
764     void testGetMatchingAccessibleMethod() {
765         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", ArrayUtils.EMPTY_CLASS_ARRAY, ArrayUtils.EMPTY_CLASS_ARRAY);
766         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", null, ArrayUtils.EMPTY_CLASS_ARRAY);
767         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(String.class), singletonArray(String.class));
768         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Object.class), singletonArray(Object.class));
769         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Boolean.class), singletonArray(Object.class));
770         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Byte.class), singletonArray(Integer.TYPE));
771         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Byte.TYPE), singletonArray(Integer.TYPE));
772         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Short.class), singletonArray(Integer.TYPE));
773         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Short.TYPE), singletonArray(Integer.TYPE));
774         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Character.class), singletonArray(Integer.TYPE));
775         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Character.TYPE), singletonArray(Integer.TYPE));
776         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Integer.class), singletonArray(Integer.class));
777         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Integer.TYPE), singletonArray(Integer.TYPE));
778         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Long.class), singletonArray(Long.TYPE));
779         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Long.TYPE), singletonArray(Long.TYPE));
780         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Float.class), singletonArray(Double.TYPE));
781         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Float.TYPE), singletonArray(Double.TYPE));
782         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.class), singletonArray(Double.TYPE));
783         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.TYPE), singletonArray(Double.TYPE));
784         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Double.TYPE), singletonArray(Double.TYPE));
785         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", new Class[] { String.class, String.class }, new Class[] { String[].class });
786         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", new Class[] { Integer.TYPE, String.class, String.class },
787                 new Class[] { Integer.class, String[].class });
788         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne", singletonArray(ParentObject.class), singletonArray(ParentObject.class));
789         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne", singletonArray(ChildObject.class), singletonArray(ParentObject.class));
790         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo", singletonArray(ParentObject.class),
791                 singletonArray(GrandParentObject.class));
792         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo", singletonArray(ChildObject.class), singletonArray(PackagePrivateEmptyInterface.class));
793         // LANG-1757
794         expectMatchingAccessibleMethodParameterTypes(Files.class, "exists", singletonArray(Path.class), new Class[] { Path.class, LinkOption[].class });
795     }
796 
797     @Test
798     void testGetMatchingMethod() throws NoSuchMethodException {
799         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod"), GetMatchingMethodClass.class.getMethod("testMethod"));
800         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", Long.TYPE),
801                 GetMatchingMethodClass.class.getMethod("testMethod", Long.TYPE));
802         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", Long.class),
803                 GetMatchingMethodClass.class.getMethod("testMethod", Long.class));
804         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod", (Class<?>) null),
805                 GetMatchingMethodClass.class.getMethod("testMethod", Long.class));
806         assertThrows(IllegalStateException.class, () -> MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod2", (Class<?>) null));
807         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.TYPE, Long.class),
808                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.TYPE, Long.class));
809         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.class, Long.TYPE),
810                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.class, Long.TYPE));
811         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", null, Long.TYPE),
812                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.class, Long.TYPE));
813         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod3", Long.TYPE, null),
814                 GetMatchingMethodClass.class.getMethod("testMethod3", Long.TYPE, Long.class));
815         assertThrows(IllegalStateException.class, () -> MethodUtils.getMatchingMethod(GetMatchingMethodClass.class, "testMethod4", null, null));
816         assertEquals(MethodUtils.getMatchingMethod(GetMatchingMethodImpl.class, "testMethod5", RuntimeException.class),
817                 GetMatchingMethodImpl.class.getMethod("testMethod5", Exception.class));
818         assertEquals(GetMatchingMethodImpl.class.getMethod("testMethod6"), MethodUtils.getMatchingMethod(GetMatchingMethodImpl.class, "testMethod6"));
819         assertNullPointerException(() -> MethodUtils.getMatchingMethod(null, "testMethod5", RuntimeException.class));
820         Method testMethod6 = MethodUtils.getMatchingMethod(ConcreteGetMatchingMethod2.class, "testMethod6");
821         assertNotNull(testMethod6);
822         assertEquals(AbstractGetMatchingMethod2.class, testMethod6.getDeclaringClass());
823         testMethod6 = MethodUtils.getMatchingMethod(ConcreteGetMatchingMethod22.class, "testMethod6");
824         assertNotNull(testMethod6);
825         assertEquals(ConcreteGetMatchingMethod22.class, testMethod6.getDeclaringClass());
826     }
827 
828     @Test
829     void testGetMethodObject() throws Exception {
830         assertEquals(MutableObject.class.getMethod("getValue", ArrayUtils.EMPTY_CLASS_ARRAY),
831                 MethodUtils.getMethodObject(MutableObject.class, "getValue", ArrayUtils.EMPTY_CLASS_ARRAY));
832         assertNull(MethodUtils.getMethodObject(MutableObject.class, "does not exist, at all", ArrayUtils.EMPTY_CLASS_ARRAY));
833         assertNull(MethodUtils.getMethodObject(null, "does not exist, at all", ArrayUtils.EMPTY_CLASS_ARRAY));
834         assertNull(MethodUtils.getMethodObject(null, null, ArrayUtils.EMPTY_CLASS_ARRAY));
835         assertNull(MethodUtils.getMethodObject(MutableObject.class, null, ArrayUtils.EMPTY_CLASS_ARRAY));
836         // 0 args
837         assertNull(MethodUtils.getMethodObject(MutableObject.class, "getValue", new Class[] { null }));
838         // 1 args
839         assertNull(MethodUtils.getMethodObject(MutableObject.class, "equals", new Class[] { null }));
840         assertNull(MethodUtils.getMethodObject(MutableObject.class, "equals", new Class[] { String.class, null, String.class }));
841     }
842 
843     /**
844      * Tests a {@code public} method.
845      */
846     @Test
847     @Annotated
848     public void testGetMethodsListWithAnnotation() throws NoSuchMethodException {
849         assertEquals(0, MethodUtils.getMethodsListWithAnnotation(Object.class, Annotated.class).size());
850         final List<Method> methodWithAnnotation = MethodUtils.getMethodsListWithAnnotation(MethodUtilsTest.class, Annotated.class);
851         assertEquals(2, methodWithAnnotation.size());
852         assertTrue(methodWithAnnotation.contains(MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation")));
853         assertTrue(methodWithAnnotation.contains(MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")));
854     }
855 
856     @Test
857     void testGetMethodsListWithAnnotationNullPointerException1() {
858         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(FieldUtilsTest.class, null));
859     }
860 
861     @Test
862     void testGetMethodsListWithAnnotationNullPointerException2() {
863         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(null, Annotated.class));
864     }
865 
866     @Test
867     void testGetMethodsListWithAnnotationNullPointerException3() {
868         assertNullPointerException(() -> MethodUtils.getMethodsListWithAnnotation(null, null));
869     }
870 
871     @Test
872     @Annotated
873     public void testGetMethodsWithAnnotation() throws NoSuchMethodException {
874         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class));
875         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(MethodUtilsTest.class, Annotated.class);
876         assertEquals(2, methodsWithAnnotation.length);
877         assertTrue(ArrayUtils.contains(methodsWithAnnotation, MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation")));
878         assertTrue(ArrayUtils.contains(methodsWithAnnotation, MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")));
879     }
880 
881     @Test
882     void testGetMethodsWithAnnotationIllegalArgumentException1() {
883         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(FieldUtilsTest.class, null));
884     }
885 
886     @Test
887     void testGetMethodsWithAnnotationIllegalArgumentException2() {
888         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(null, Annotated.class));
889     }
890 
891     @Test
892     void testGetMethodsWithAnnotationIllegalArgumentException3() {
893         assertNullPointerException(() -> MethodUtils.getMethodsWithAnnotation(null, null));
894     }
895 
896     @Test
897     void testGetMethodsWithAnnotationNotSearchSupersAndNotIgnoreAccess() {
898         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, false, false));
899         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, false, false);
900         assertEquals(1, methodsWithAnnotation.length);
901         assertEquals("PublicChild.publicAnnotatedMethod",
902                 methodsWithAnnotation[0].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[0].getName());
903     }
904 
905     @Test
906     void testGetMethodsWithAnnotationNotSearchSupersButIgnoreAccess() {
907         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, false, true));
908         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, false, true);
909         assertEquals(2, methodsWithAnnotation.length);
910         assertEquals("PublicChild", methodsWithAnnotation[0].getDeclaringClass().getSimpleName());
911         assertEquals("PublicChild", methodsWithAnnotation[1].getDeclaringClass().getSimpleName());
912         assertTrue(methodsWithAnnotation[0].getName().endsWith("AnnotatedMethod"));
913         assertTrue(methodsWithAnnotation[1].getName().endsWith("AnnotatedMethod"));
914     }
915 
916     @Test
917     void testGetMethodsWithAnnotationSearchSupersAndIgnoreAccess() {
918         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, true, true));
919         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, true, true);
920         assertEquals(4, methodsWithAnnotation.length);
921         assertEquals("PublicChild", methodsWithAnnotation[0].getDeclaringClass().getSimpleName());
922         assertEquals("PublicChild", methodsWithAnnotation[1].getDeclaringClass().getSimpleName());
923         assertTrue(methodsWithAnnotation[0].getName().endsWith("AnnotatedMethod"));
924         assertTrue(methodsWithAnnotation[1].getName().endsWith("AnnotatedMethod"));
925         assertEquals("Foo.doIt", methodsWithAnnotation[2].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[2].getName());
926         assertEquals("Parent.parentProtectedAnnotatedMethod",
927                 methodsWithAnnotation[3].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[3].getName());
928     }
929 
930     @Test
931     void testGetMethodsWithAnnotationSearchSupersButNotIgnoreAccess() {
932         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class, true, false));
933         final Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(PublicChild.class, Annotated.class, true, false);
934         assertEquals(2, methodsWithAnnotation.length);
935         assertEquals("PublicChild.publicAnnotatedMethod",
936                 methodsWithAnnotation[0].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[0].getName());
937         assertEquals("Foo.doIt", methodsWithAnnotation[1].getDeclaringClass().getSimpleName() + '.' + methodsWithAnnotation[1].getName());
938     }
939 
940     @Test
941     void testGetOverrideHierarchyExcludingInterfaces() {
942         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
943         final Iterator<MethodDescriptor> expected =
944                 Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
945                         new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]))
946                         .iterator();
947         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.EXCLUDE)) {
948             assertTrue(expected.hasNext());
949             final MethodDescriptor md = expected.next();
950             assertEquals(md.declaringClass, m.getDeclaringClass());
951             assertEquals(md.name, m.getName());
952             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
953             for (int i = 0; i < md.parameterTypes.length; i++) {
954                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
955             }
956         }
957         assertFalse(expected.hasNext());
958     }
959 
960     @Test
961     void testGetOverrideHierarchyIncludingInterfaces() {
962         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
963         final Iterator<MethodDescriptor> expected =
964                 Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
965                         new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]),
966                         new MethodDescriptor(GenericConsumer.class, "consume", GenericConsumer.class.getTypeParameters()[0]))
967                         .iterator();
968         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.INCLUDE)) {
969             assertTrue(expected.hasNext());
970             final MethodDescriptor md = expected.next();
971             assertEquals(md.declaringClass, m.getDeclaringClass());
972             assertEquals(md.name, m.getName());
973             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
974             for (int i = 0; i < md.parameterTypes.length; i++) {
975                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
976             }
977         }
978         assertFalse(expected.hasNext());
979     }
980 
981     @Test
982     void testInvokeExactMethod() throws Exception {
983         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
984         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo"));
985         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", (Object[]) null));
986         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", null, null));
987         assertEquals("foo(String)", MethodUtils.invokeExactMethod(testBean, "foo", ""));
988         assertEquals("foo(Object)", MethodUtils.invokeExactMethod(testBean, "foo", new Object()));
989         assertEquals("foo(Integer)", MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.INTEGER_ONE));
990         assertEquals("foo(double)", MethodUtils.invokeExactMethod(testBean, "foo", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
991         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.BYTE_ONE));
992         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", NumberUtils.LONG_ONE));
993         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, "foo", Boolean.TRUE));
994         assertThrows(NullPointerException.class, () -> MethodUtils.invokeExactMethod(null, "foo", NumberUtils.BYTE_ONE));
995         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactMethod(testBean, null, NumberUtils.BYTE_ONE));
996         assertThrows(NullPointerException.class,
997                 () -> MethodUtils.invokeExactMethod(null, "foo", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
998         assertThrows(NoSuchMethodException.class,
999                 () -> MethodUtils.invokeExactMethod(testBean, null, new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1000     }
1001 
1002     @Test
1003     void testInvokeExactStaticMethod() throws Exception {
1004         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1005         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", (Object[]) null));
1006         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", null, null));
1007         assertEquals("bar(String)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", ""));
1008         assertEquals("bar(Object)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", new Object()));
1009         assertEquals("bar(Integer)", MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE));
1010         assertEquals("bar(double)",
1011                 MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", new Object[] { NumberUtils.DOUBLE_ONE }, new Class[] { Double.TYPE }));
1012         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.BYTE_ONE));
1013         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", NumberUtils.LONG_ONE));
1014         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeExactStaticMethod(TestBean.class, "bar", Boolean.TRUE));
1015     }
1016 
1017     @Test
1018     void testInvokeJavaVarArgsOverloadingResolution() throws Exception {
1019         // Primitive wrappers
1020         assertEquals("Byte...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (byte) 1, (byte) 2));
1021         assertEquals("Short...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (short) 1, (short) 2));
1022         assertEquals("Integer...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 2));
1023         assertEquals("Long...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1L, 2L));
1024         assertEquals("Float...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1f, 2f));
1025         assertEquals("Double...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1d, 2d));
1026         assertEquals("Boolean...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", true, false));
1027         // Number
1028         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 1.1));
1029         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 1L));
1030         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1d, 1f));
1031         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (short) 1, (byte) 1));
1032         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", ArrayUtils.EMPTY_OBJECT_ARRAY));
1033         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1034         assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload", (Object[]) ArrayUtils.EMPTY_INTEGER_OBJECT_ARRAY));
1035         // Object
1036         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, "s"));
1037         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, true));
1038         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1.1, true));
1039         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'c', true));
1040         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 1, 'c'));
1041         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'c', "s"));
1042         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", ArrayUtils.EMPTY_OBJECT_ARRAY));
1043         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1044         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", (Object[]) ArrayUtils.EMPTY_INTEGER_OBJECT_ARRAY));
1045         assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload"));
1046         // Other
1047         assertEquals("String...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", "a", "b"));
1048         assertEquals("Character...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload", 'a', 'b'));
1049     }
1050 
1051     @Test
1052     void testInvokeMethod() throws Exception {
1053         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1054         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo"));
1055         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", (Object[]) null));
1056         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", null, null));
1057         assertEquals("foo(String)", MethodUtils.invokeMethod(testBean, "foo", ""));
1058         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo", new Object()));
1059         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo", Boolean.TRUE));
1060         assertEquals("foo(Integer)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.INTEGER_ONE));
1061         assertEquals("foo(int)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.BYTE_ONE));
1062         assertEquals("foo(long)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.LONG_ONE));
1063         assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.DOUBLE_ONE));
1064         assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo", "a", "b", "c"));
1065         assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo", "a", "b", "c"));
1066         assertEquals("foo(int, String...)", MethodUtils.invokeMethod(testBean, "foo", 5, "a", "b", "c"));
1067         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", 1L, 2L));
1068         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", 1, 2));
1069         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (byte) 1, (byte) 2)); // widen
1070         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (short) 1, (short) 2)); // widen
1071         assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", (char) 1, (char) 2)); // widen
1072         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y"));
1073         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", 17, 23, 42));
1074         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y"));
1075         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }), MethodUtils.invokeMethod(testBean, "varOverloadEcho", 17, 23, 42));
1076         assertNullPointerException(() -> MethodUtils.invokeMethod(null, "foo", 1, 2));
1077         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, null, 1, 2));
1078         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(new Object(), "nonExistent", new Object[] { "val" }, new Class<?>[] { null }));
1079     }
1080 
1081     @Test
1082     void testInvokeMethod_VarArgsWithNullValues() throws Exception {
1083         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", "a", null, "c"));
1084         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", "a", "b", null));
1085         assertEquals("String...", MethodUtils.invokeMethod(testBean, "varOverload", new String[] { "a" }, new Class<?>[] { String.class }));
1086         assertThrows(NoSuchMethodException.class,
1087                 () -> assertEquals("String...", MethodUtils.invokeMethod(testBean, "doesn't exist", new String[] { "a" }, new Class<?>[] { null })));
1088     }
1089 
1090     @Test
1091     void testInvokeMethod1PlusVarArgs() throws Exception {
1092         // intStringVarArg
1093         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1));
1094         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s"));
1095         assertEquals("int, String...", MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s1", "s2"));
1096         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intStringVarArg", 1, "s1", 5));
1097         // intLongVarArg
1098         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1));
1099         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, 2L));
1100         assertEquals("int, long...", MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, 2L, 3L));
1101         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, "s1", 5));
1102         // intIntVarArg
1103         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1));
1104         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1, 2));
1105         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, "intIntVarArg", 1, 2, 3));
1106         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, "s1", 5));
1107     }
1108 
1109     @Test
1110     void testInvokeMethodForceAccessNoArgs() throws Exception {
1111         assertEquals("privateStringStuff()", MethodUtils.invokeMethod(testBean, true, "privateStringStuff"));
1112     }
1113 
1114     @Test
1115     void testInvokeMethodForceAccessWithArgs() throws Exception {
1116         assertEquals("privateStringStuff(Integer)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", 5));
1117         assertEquals("privateStringStuff(double)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", 5.0d));
1118         assertEquals("privateStringStuff(String)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", "Hi There"));
1119         assertEquals("privateStringStuff(Object)", MethodUtils.invokeMethod(testBean, true, "privateStringStuff", new Date()));
1120         assertNullPointerException(() -> MethodUtils.invokeMethod(null, true, "privateStringStuff", "Hi There"));
1121         assertNullPointerException(() -> MethodUtils.invokeMethod(testBean, true, null, "Hi There"));
1122     }
1123 
1124     @Test
1125     void testInvokeMethodVarArgsNotUniqueResolvable() throws Exception {
1126         assertEquals("Boolean...", MethodUtils.invokeMethod(testBean, "varOverload", new Object[] { null }));
1127         assertEquals("Object...", MethodUtils.invokeMethod(testBean, "varOverload", (Object[]) null));
1128     }
1129 
1130     @Test
1131     void testInvokeMethodVarArgsOfInterface() throws Exception {
1132         // packagePrivateEmptyInterface
1133         assertEquals("PackagePrivateEmptyInterface...", MethodUtils.invokeMethod(testBean, "packagePrivateEmptyInterface",
1134                 new PublicImpl1OfPackagePrivateEmptyInterface(), new PublicImpl2OfPackagePrivateEmptyInterface()));
1135         assertEquals("PackagePrivateEmptyInterface...", MethodUtils.invokeMethod(testBean, "packagePrivateEmptyInterface", new PackagePrivateEmptyInterface() {
1136             // empty
1137         }, new PackagePrivateEmptyInterface() {
1138             // empty
1139         }));
1140     }
1141 
1142     @Test
1143     void testInvokeMethodVarArgsUnboxingBooleanArray() throws Exception {
1144         final TestBean testBean = new TestBean();
1145         final boolean[] actual = (boolean[]) MethodUtils.invokeMethod(testBean, "unboxing", Boolean.TRUE, Boolean.FALSE);
1146         assertArrayEquals(new boolean[] { true, false }, actual);
1147         assertTrue(testBean.unboxBooleanArray);
1148     }
1149 
1150     @Test
1151     void testInvokeMethodVarArgsUnboxingByteArray() throws Exception {
1152         final TestBean testBean = new TestBean();
1153         final byte[] actual = (byte[]) MethodUtils.invokeMethod(testBean, "unboxing", Byte.valueOf((byte) 1), Byte.valueOf((byte) 2));
1154         assertArrayEquals(new byte[] { 1, 2 }, actual);
1155         assertTrue(testBean.unboxByteArray);
1156     }
1157 
1158     @Test
1159     void testInvokeMethodVarArgsUnboxingCharArray() throws Exception {
1160         final TestBean testBean = new TestBean();
1161         final char[] actual = (char[]) MethodUtils.invokeMethod(testBean, "unboxing", Character.valueOf((char) 1), Character.valueOf((char) 2));
1162         assertArrayEquals(new char[] { 1, 2 }, actual);
1163         assertTrue(testBean.unboxCharArray);
1164     }
1165 
1166     @Test
1167     void testInvokeMethodVarArgsUnboxingDoubleArray() throws Exception {
1168         final TestBean testBean = new TestBean();
1169         final double[] actual = (double[]) MethodUtils.invokeMethod(testBean, "unboxing", Double.valueOf(1), Double.valueOf(2));
1170         assertArrayEquals(new double[] { 1, 2 }, actual);
1171         assertTrue(testBean.unboxDoubleArray);
1172     }
1173 
1174     @Test
1175     void testInvokeMethodVarArgsUnboxingFloatArray() throws Exception {
1176         final TestBean testBean = new TestBean();
1177         final float[] actual = (float[]) MethodUtils.invokeMethod(testBean, "unboxing", Float.valueOf(1), Float.valueOf(2));
1178         assertArrayEquals(new float[] { 1, 2 }, actual);
1179         assertTrue(testBean.unboxFloatArray);
1180     }
1181 
1182     @Test
1183     void testInvokeMethodVarArgsUnboxingIntArray() throws Exception {
1184         final TestBean testBean = new TestBean();
1185         final int[] actual = (int[]) MethodUtils.invokeMethod(testBean, "unboxing", Integer.valueOf(1), Integer.valueOf(2));
1186         assertArrayEquals(new int[] { 1, 2 }, actual);
1187         assertTrue(testBean.unboxIntArray);
1188     }
1189 
1190     @Test
1191     void testInvokeMethodVarArgsUnboxingLongArray() throws Exception {
1192         final TestBean testBean = new TestBean();
1193         final long[] actual = (long[]) MethodUtils.invokeMethod(testBean, "unboxing", Long.valueOf(1), Long.valueOf(2));
1194         assertArrayEquals(new long[] { 1, 2 }, actual);
1195         assertTrue(testBean.unboxLongArray);
1196     }
1197 
1198     @Test
1199     void testInvokeMethodVarArgsUnboxingShortArray() throws Exception {
1200         final TestBean testBean = new TestBean();
1201         final short[] actual = (short[]) MethodUtils.invokeMethod(testBean, "unboxing", Short.valueOf((short) 1), Short.valueOf((short) 2));
1202         assertArrayEquals(new short[] { 1, 2 }, actual);
1203         assertTrue(testBean.unboxShortArray);
1204     }
1205 
1206     @Test
1207     void testInvokeStaticMethod() throws Exception {
1208         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar"));
1209         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
1210         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (Object[]) null));
1211         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class, "bar", null, null));
1212         assertEquals("bar(String)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", ""));
1213         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", new Object()));
1214         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", Boolean.TRUE));
1215         assertEquals("bar(Integer)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE));
1216         assertEquals("bar(int)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.BYTE_ONE));
1217         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.BYTE_ONE));
1218         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.SHORT_ONE));
1219         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", NumberUtils.INTEGER_ONE));
1220         assertEquals("static int", MethodUtils.invokeStaticMethod(TestBean.class, "staticInt", 'a'));
1221         assertEquals("bar(double)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
1222         assertEquals("bar(String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", "a", "b"));
1223         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", 1L, 2L));
1224         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (byte) 1, (byte) 2)); // widen
1225         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", (short) 1, (short) 2)); // widen
1226         assertEquals("bar(long...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", 1, 2)); // widen
1227         assertEquals("bar(Integer, String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.INTEGER_ONE, "a", "b"));
1228         // 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.
1229         assertThrows(NoSuchMethodException.class,
1230                 () -> assertEquals("bar(Integer, String...)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.SHORT_ONE, "a", "b"))); // widen
1231         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }),
1232                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", "x", "y"));
1233         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }),
1234                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", 17, 23, 42));
1235         TestBean.verify(new ImmutablePair<>("String...", new String[] { "x", "y" }),
1236                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", "x", "y"));
1237         TestBean.verify(new ImmutablePair<>("Number...", new Number[] { 17, 23, 42 }),
1238                 MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", 17, 23, 42));
1239         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeStaticMethod(TestBean.class, "does_not_exist"));
1240     }
1241 
1242     @Test
1243     void testInvokeStaticMethod1PlusVarArgs() throws Exception {
1244         // staticIntStringVarArg
1245         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1));
1246         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s"));
1247         assertEquals("static int, String...", MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s1", "s2"));
1248         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg", 1, "s1", 5));
1249         // staticIntLongVarArg
1250         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1));
1251         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, 2L));
1252         assertEquals("static int, long...", MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, 2L, 3L));
1253         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "staticIntLongVarArg", 1, "s1", 5));
1254         // staticIntIntVarArg
1255         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1));
1256         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, 2));
1257         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, 2, 3));
1258         assertThrows(NoSuchMethodException.class, () -> MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, "s1", 5));
1259     }
1260 
1261     @Test
1262     void testInvokeStaticMethodVarArgsOfInterface() throws Exception {
1263         // staticPackagePrivateEmptyInterface
1264         assertEquals("static PackagePrivateEmptyInterface...", MethodUtils.invokeStaticMethod(TestBean.class, "staticPackagePrivateEmptyInterface",
1265                 new PublicImpl1OfPackagePrivateEmptyInterface(), new PublicImpl2OfPackagePrivateEmptyInterface()));
1266         assertEquals("static PackagePrivateEmptyInterface...",
1267                 MethodUtils.invokeStaticMethod(TestBean.class, "staticPackagePrivateEmptyInterface", new PackagePrivateEmptyInterface() {
1268                     // empty
1269                 }, new PackagePrivateEmptyInterface() {
1270                     // empty
1271                 }));
1272     }
1273 
1274     @Test
1275     void testNullArgument() {
1276         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "oneParameter", singletonArray(null), singletonArray(String.class));
1277     }
1278 
1279     @Test
1280     void testVarargsOverloadingResolution() {
1281         // This code is not a test of MethodUtils.
1282         // Rather it makes explicit the behavior of the Java specification for
1283         // various cases of overload resolution.
1284         assertEquals("Byte...", TestBean.varOverload((byte) 1, (byte) 2));
1285         assertEquals("Short...", TestBean.varOverload((short) 1, (short) 2));
1286         assertEquals("Integer...", TestBean.varOverload(1, 2));
1287         assertEquals("Long...", TestBean.varOverload(1L, 2L));
1288         assertEquals("Float...", TestBean.varOverload(1f, 2f));
1289         assertEquals("Double...", TestBean.varOverload(1d, 2d));
1290         assertEquals("Character...", TestBean.varOverload('a', 'b'));
1291         assertEquals("String...", TestBean.varOverload("a", "b"));
1292         assertEquals("Boolean...", TestBean.varOverload(true, false));
1293         assertEquals("Object...", TestBean.varOverload(1, "s"));
1294         assertEquals("Object...", TestBean.varOverload(1, true));
1295         assertEquals("Object...", TestBean.varOverload(1.1, true));
1296         assertEquals("Object...", TestBean.varOverload('c', true));
1297         assertEquals("Number...", TestBean.varOverload(1, 1.1));
1298         assertEquals("Number...", TestBean.varOverload(1, 1L));
1299         assertEquals("Number...", TestBean.varOverload(1d, 1f));
1300         assertEquals("Number...", TestBean.varOverload((short) 1, (byte) 1));
1301         assertEquals("Object...", TestBean.varOverload(1, 'c'));
1302         assertEquals("Object...", TestBean.varOverload('c', "s"));
1303     }
1304 
1305     private String toString(final Class<?>[] c) {
1306         return Arrays.asList(c).toString();
1307     }
1308 }