Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Modifier;
- /**
- * @param <T> The type to call the constructor of.
- * @param <E> Optionally, the enclosing type if T is an inner non-static class.
- */
- public class New<T, E> {
- private final Constructor<T> constructor;
- private final Class<T> type;
- private final Class<?>[] argTypes;
- /**
- * Must be not null if and only if type is an inner non-static class.
- */
- private final Class<E> enclosingType;
- /**
- * Must be not null if and only if type is an inner non-static class.
- */
- private final E enclosingInstance;
- public Class<T> getType() {
- return type;
- }
- public Class<?> getArgType(int index) {
- return argTypes[index];
- }
- protected New(Class<E> enclosingType, E enclosingInstance, Class<T> type, Class<?>[] argTypes) throws NoSuchMethodException {
- this.type = type;
- this.enclosingInstance = enclosingInstance;
- this.argTypes = argTypes;
- this.enclosingType = enclosingType;
- if ((enclosingType == null) != (enclosingInstance == null)) {
- throw new IllegalArgumentException("enclosingType and enclosingInstance must be both either not null or null");
- }
- // create sure enclosingInstance != null is true if and only if type is an inner non-static class.
- if ((type.getEnclosingClass() != null && !Modifier.isStatic(type.getModifiers())) == (enclosingInstance == null)) {
- throw new NoSuchMethodException("enclosingInstance must not be null if type is an inner non-static class");
- }
- Class<?>[] constructorArgs = argTypes;
- // if is inner non-static class, need to prepend the instance type
- if (enclosingInstance != null) {
- constructorArgs = new Class<?>[argTypes.length + 1];
- constructorArgs[0] = enclosingType;
- System.arraycopy(argTypes, 0, constructorArgs, 1, argTypes.length);
- }
- constructor = type.getConstructor(constructorArgs); // should only get a public constructor, therefore callable
- }
- public static <T> New<T, Object> create(Class<T> type, Class<?>[] argTypes) throws NoSuchMethodException {
- return create(null, type, argTypes);
- }
- /**
- * @param type The Class of which to get the constructor matching args(.getReturnType()) and to call it for each execute(..).
- * @param enclosingInstance If type is a non-static inner class, this will be {@code enclosingInstance.new}
- * @param argTypes Argument types (without enclosing type)
- * @throws NoSuchMethodException If no (public) constructor exists with args.
- */
- @SuppressWarnings("unchecked")
- public static <T, E> New<T, E> create(E enclosingInstance, Class<T> type, Class<?>... argTypes) throws NoSuchMethodException {
- return new New<>((Class<E>) enclosingInstance.getClass(), enclosingInstance, type, argTypes);
- }
- /**
- * @param args Arguments to pass along to the constructor. (don't pass the enclosing instance here)
- * @return a new instance.
- * @throws InvocationTargetException If the constructor throws an exception.
- */
- public T make(Object... args) throws InvocationTargetException {
- // prepend enclosing instance to arguments for Constructor.newInstance
- Object[] argsWithPossiblyEnclosingInstance = args;
- if (enclosingInstance != null) {
- argsWithPossiblyEnclosingInstance = new Object[args.length + 1];
- System.arraycopy(args, 0, argsWithPossiblyEnclosingInstance, 1, args.length);
- argsWithPossiblyEnclosingInstance[0] = enclosingInstance;
- }
- T instance;
- try {
- instance = constructor.newInstance(argsWithPossiblyEnclosingInstance);
- } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e) {
- // IllegalAccessException: shouldn't be thrown because getConstructor returns only public constructors.
- throw new RuntimeException("this is a software bug; the constructor could not be invoked: "
- + e.getMessage(), e);
- }
- return instance;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement