View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.internal.reflection;
7   
8   import static mockit.internal.reflection.ParameterReflection.getParameterTypesDescription;
9   import static mockit.internal.reflection.ParameterReflection.indexOfFirstRealParameter;
10  import static mockit.internal.reflection.ParameterReflection.matchesParameterTypes;
11  import static mockit.internal.util.Utilities.ensureThatMemberIsAccessible;
12  
13  import edu.umd.cs.findbugs.annotations.NonNull;
14  import edu.umd.cs.findbugs.annotations.Nullable;
15  
16  import java.lang.reflect.Constructor;
17  import java.lang.reflect.InvocationTargetException;
18  
19  import org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator;
20  
21  public final class ConstructorReflection {
22      private ConstructorReflection() {
23      }
24  
25      @NonNull
26      static <T> Constructor<T> findSpecifiedConstructor(@NonNull Class<?> theClass, @NonNull Class<?>[] paramTypes) {
27          for (Constructor<?> declaredConstructor : theClass.getDeclaredConstructors()) {
28              Class<?>[] declaredParameterTypes = declaredConstructor.getParameterTypes();
29              int firstRealParameter = indexOfFirstRealParameter(declaredParameterTypes, paramTypes);
30  
31              if (firstRealParameter >= 0
32                      && matchesParameterTypes(declaredParameterTypes, paramTypes, firstRealParameter)) {
33                  // noinspection unchecked
34                  return (Constructor<T>) declaredConstructor;
35              }
36          }
37  
38          String paramTypesDesc = getParameterTypesDescription(paramTypes);
39  
40          throw new IllegalArgumentException(
41                  "Specified constructor not found: " + theClass.getSimpleName() + paramTypesDesc);
42      }
43  
44      @NonNull
45      public static <T> T invokeAccessible(@NonNull Constructor<T> constructor, @NonNull Object... initArgs) {
46          if (!constructor.isAccessible()) {
47              constructor.setAccessible(true);
48          }
49          try {
50              return constructor.newInstance(initArgs);
51          } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
52              Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e;
53  
54              if (cause instanceof Error) {
55                  throw (Error) cause;
56              }
57              if (cause instanceof RuntimeException) {
58                  throw (RuntimeException) cause;
59              }
60              ThrowOfCheckedException.doThrow((Exception) cause);
61              throw new IllegalStateException("Should never get here", cause);
62          }
63      }
64  
65      public static void newInstanceUsingCompatibleConstructor(@NonNull Class<?> aClass, @NonNull String argument)
66              throws ReflectiveOperationException {
67          Constructor<?> constructor = aClass.getDeclaredConstructor(String.class);
68          ensureThatMemberIsAccessible(constructor);
69          constructor.newInstance(argument);
70      }
71  
72      @NonNull
73      public static <T> T newInstanceUsingDefaultConstructor(@NonNull Class<T> aClass) {
74          try {
75              Constructor<T> constructor = aClass.getDeclaredConstructor();
76              ensureThatMemberIsAccessible(constructor);
77              return constructor.newInstance();
78          } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
79              throw new RuntimeException(e);
80          } catch (InvocationTargetException e) {
81              throw new RuntimeException(e.getTargetException());
82          }
83      }
84  
85      @Nullable
86      public static <T> T newInstanceUsingDefaultConstructorIfAvailable(@NonNull Class<T> aClass) {
87          try {
88              Constructor<T> constructor = aClass.getDeclaredConstructor();
89              return constructor.newInstance();
90          } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
91                  | InvocationTargetException ignore) {
92              return null;
93          }
94      }
95  
96      @Nullable
97      public static <T> T newInstanceUsingPublicConstructorIfAvailable(@NonNull Class<T> aClass,
98              @NonNull Class<?>[] parameterTypes, @NonNull Object... initArgs) {
99          Constructor<T> publicConstructor;
100         try {
101             publicConstructor = aClass.getConstructor(parameterTypes);
102         } catch (NoSuchMethodException ignore) {
103             return null;
104         }
105 
106         return invokeAccessible(publicConstructor, initArgs);
107     }
108 
109     @NonNull
110     public static <T> T newInstanceUsingPublicDefaultConstructor(@NonNull Class<T> aClass) {
111         Constructor<T> publicConstructor;
112         try {
113             publicConstructor = aClass.getConstructor();
114         } catch (NoSuchMethodException e) {
115             throw new RuntimeException(e);
116         }
117 
118         return invokeAccessible(publicConstructor);
119     }
120 
121     @NonNull
122     public static <T> T newUninitializedInstance(@NonNull Class<T> aClass) {
123         SunReflectionFactoryInstantiator<T> ref = new SunReflectionFactoryInstantiator<>(aClass);
124         return ref.newInstance();
125     }
126 }