Advertisement
Guest User

New.java

a guest
Aug 19th, 2016
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.26 KB | None | 0 0
  1. import java.lang.reflect.Constructor;
  2. import java.lang.reflect.InvocationTargetException;
  3. import java.lang.reflect.Modifier;
  4.  
  5. /**
  6.  * @param <T> The type to call the constructor of.
  7.  * @param <E> Optionally, the enclosing type if T is an inner non-static class.
  8.  */
  9. public class New<T, E> {
  10.     private final Constructor<T> constructor;
  11.     private final Class<T> type;
  12.     private final Class<?>[] argTypes;
  13.  
  14.     /**
  15.      * Must be not null if and only if type is an inner non-static class.
  16.      */
  17.     private final Class<E> enclosingType;
  18.  
  19.     /**
  20.      * Must be not null if and only if type is an inner non-static class.
  21.      */
  22.     private final E enclosingInstance;
  23.  
  24.     public Class<T> getType() {
  25.         return type;
  26.     }
  27.  
  28.     public Class<?> getArgType(int index) {
  29.         return argTypes[index];
  30.     }
  31.  
  32.     protected New(Class<E> enclosingType, E enclosingInstance, Class<T> type, Class<?>[] argTypes) throws NoSuchMethodException {
  33.         this.type = type;
  34.         this.enclosingInstance = enclosingInstance;
  35.         this.argTypes = argTypes;
  36.         this.enclosingType = enclosingType;
  37.  
  38.         if ((enclosingType == null) != (enclosingInstance == null)) {
  39.             throw new IllegalArgumentException("enclosingType and enclosingInstance must be both either not null or null");
  40.         }
  41.  
  42.         // create sure enclosingInstance != null is true if and only if type is an inner non-static class.
  43.         if ((type.getEnclosingClass() != null && !Modifier.isStatic(type.getModifiers())) == (enclosingInstance == null)) {
  44.             throw new NoSuchMethodException("enclosingInstance must not be null if type is an inner non-static class");
  45.         }
  46.  
  47.         Class<?>[] constructorArgs = argTypes;
  48.         // if is inner non-static class, need to prepend the instance type
  49.         if (enclosingInstance != null) {
  50.             constructorArgs = new Class<?>[argTypes.length + 1];
  51.             constructorArgs[0] = enclosingType;
  52.             System.arraycopy(argTypes, 0, constructorArgs, 1, argTypes.length);
  53.         }
  54.         constructor = type.getConstructor(constructorArgs); // should only get a public constructor, therefore callable
  55.     }
  56.  
  57.     public static <T> New<T, Object> create(Class<T> type, Class<?>[] argTypes) throws NoSuchMethodException {
  58.         return create(null, type, argTypes);
  59.     }
  60.  
  61.     /**
  62.      * @param type              The Class of which to get the constructor matching args(.getReturnType()) and to call it for each execute(..).
  63.      * @param enclosingInstance If type is a non-static inner class, this will be {@code enclosingInstance.new}
  64.      * @param argTypes          Argument types (without enclosing type)
  65.      * @throws NoSuchMethodException If no (public) constructor exists with args.
  66.      */
  67.     @SuppressWarnings("unchecked")
  68.     public static <T, E> New<T, E> create(E enclosingInstance, Class<T> type, Class<?>... argTypes) throws NoSuchMethodException {
  69.         return new New<>((Class<E>) enclosingInstance.getClass(), enclosingInstance, type, argTypes);
  70.     }
  71.  
  72.     /**
  73.      * @param args Arguments to pass along to the constructor. (don't pass the enclosing instance here)
  74.      * @return a new instance.
  75.      * @throws InvocationTargetException If the constructor throws an exception.
  76.      */
  77.     public T make(Object... args) throws InvocationTargetException {
  78.         // prepend enclosing instance to arguments for Constructor.newInstance
  79.         Object[] argsWithPossiblyEnclosingInstance = args;
  80.         if (enclosingInstance != null) {
  81.             argsWithPossiblyEnclosingInstance = new Object[args.length + 1];
  82.             System.arraycopy(args, 0, argsWithPossiblyEnclosingInstance, 1, args.length);
  83.             argsWithPossiblyEnclosingInstance[0] = enclosingInstance;
  84.         }
  85.  
  86.         T instance;
  87.         try {
  88.             instance = constructor.newInstance(argsWithPossiblyEnclosingInstance);
  89.         } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e) {
  90.             // IllegalAccessException: shouldn't be thrown because getConstructor returns only public constructors.
  91.             throw new RuntimeException("this is a software bug; the constructor could not be invoked: "
  92.                     + e.getMessage(), e);
  93.         }
  94.         return instance;
  95.     }
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement