Java Class New Instance newInstance(Class type)

Here you can find the source of newInstance(Class type)

Description

Creates a new instance of the given type by invoking the default constructor.

License

Open Source License

Parameter

Parameter Description
T the type to instantiate
type the type to instantiate

Exception

Parameter Description
IllegalArgumentException if the type has no accessible default constructor or an exception occurred during the invocation: possible causes areNoSuchMethodException, InstantiationException , IllegalAccessException, * InvocationTargetException

Return

the created instance

Declaration

@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> type) throws IllegalArgumentException 

Method Source Code

//package com.java2s;
/*//from www  .j  av a 2s .  c o  m
 * DuDe - The Duplicate Detection Toolkit
 * 
 * Copyright (C) 2010  Hasso-Plattner-Institut f?r Softwaresystemtechnik GmbH,
 *                     Potsdam, Germany 
 *
 * This file is part of DuDe.
 * 
 * DuDe is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DuDe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DuDe.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

import java.lang.reflect.Constructor;

import java.util.Arrays;
import java.util.HashMap;

import java.util.Map;
import java.util.Map.Entry;

public class Main {
    private static Map<Class<?>, Constructor<?>> CACHED_DEFAULT_CONSTRUCTORS = new HashMap<Class<?>, Constructor<?>>();

    /**
     * Creates a new instance of the given type by invoking the default constructor. If the default constructor is not public, the method will try to
     * gain access through {@link Constructor#setAccessible(boolean)}. <br>
     * <br>
     * Note: this method is not thread-safe
     * 
     * @param <T>
     *            the type to instantiate
     * @param type
     *            the type to instantiate
     * @return the created instance
     * @throws IllegalArgumentException
     *             if the type has no accessible default constructor or an exception occurred during the invocation: possible causes are
     *             {@link NoSuchMethodException}, {@link InstantiationException} , {@link IllegalAccessException}, * {@link InvocationTargetException}
     */
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<T> type) throws IllegalArgumentException {
        try {
            Constructor<T> constructor = (Constructor<T>) CACHED_DEFAULT_CONSTRUCTORS.get(type);
            if (constructor == null) {
                CACHED_DEFAULT_CONSTRUCTORS.put(type, constructor = type.getDeclaredConstructor());
                constructor.setAccessible(true);
            }
            return constructor.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not create an instance of type " + type, e);
        }
    }

    /**
     * Creates a new instance of the given type by invoking the best public constructor for the given parameter.<br>
     * If there are multiple compatible constructors, the most specific one is chosen. <br>
     * If there are several constructors with the same degree of specify, an Exception is thrown. <br>
     * Note: this method is thread-safe
     * 
     * @param <T>
     *            the type to instantiate
     * @param type
     *            the type to instantiate
     * @param params
     *            The constructors parameters.
     * @return the created instance
     * @throws IllegalArgumentException
     *             if the type has 0 or more than 2 matching constructors or an exception occurred during the invocation: possible causes are
     *             {@link NoSuchMethodException}, {@link InstantiationException} , {@link IllegalAccessException}, {@link InvocationTargetException}
     */
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<T> type, Object... params) throws IllegalArgumentException {
        try {
            Map<Constructor<?>, Integer> candidateDistances = getCompatibleConstructors(type, params);

            if (candidateDistances.isEmpty())
                throw new IllegalArgumentException(
                        String.format("no suitable constructor found in %s for %s", type, Arrays.toString(params)));

            if (candidateDistances.size() == 1)
                return (T) candidateDistances.keySet().iterator().next().newInstance(params);

            Constructor<?> bestConstructor = pickBest(candidateDistances);
            if (bestConstructor == null)
                throw new IllegalArgumentException(String.format(
                        "more than one suitable constructor found in %s for %s", type, Arrays.toString(params)));
            return (T) bestConstructor.newInstance(params);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not create an instance of type " + type, e);
        }
    }

    private static <T> Map<Constructor<?>, Integer> getCompatibleConstructors(Class<T> type, Object... params) {
        Constructor<?>[] constructors = type.getDeclaredConstructors();
        Map<Constructor<?>, Integer> candidateDistances = new HashMap<Constructor<?>, Integer>();
        for (Constructor<?> constructor : constructors) {
            int distance = 0;
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            if (params.length != parameterTypes.length)
                continue;

            for (int index = 0; index < parameterTypes.length; index++) {
                if (!parameterTypes[index].isInstance(params[index])) {
                    distance = Integer.MAX_VALUE;
                    break;
                }

                if (params[index] != null)
                    distance += getDistance(parameterTypes[index], params[index].getClass());
            }
            candidateDistances.put(constructor, distance);
        }
        return candidateDistances;
    }

    private static <T> T pickBest(Map<T, Integer> candidateDistances) {
        int minDistance = Integer.MAX_VALUE;
        int minCount = 0;
        T minConstructor = null;
        for (Entry<T, Integer> entry : candidateDistances.entrySet())
            if (entry.getValue() < minDistance) {
                minDistance = entry.getValue();
                minConstructor = entry.getKey();
                minCount = 1;
            } else if (entry.getValue() == minDistance) {
                minCount++;
            }

        return minCount == 1 ? minConstructor : null;
    }

    private static int getDistance(Class<?> superClass, Class<?> subclass) {
        if (superClass == subclass)
            return 0;
        if (!superClass.isAssignableFrom(subclass))
            return Integer.MAX_VALUE;

        if (superClass.isInterface()) {
            Class<?>[] interfaces = subclass.getInterfaces();
            int minDistance = Integer.MAX_VALUE;
            for (Class<?> xface : interfaces) {
                if (xface == superClass) {
                    minDistance = 1;
                    break;
                } else if (superClass.isAssignableFrom(xface))
                    minDistance = Math.min(minDistance, getDistance(superClass, xface));
            }
        }

        int distance = 1;
        for (Class<?> klazz = subclass; superClass != klazz; distance++)
            klazz = klazz.getSuperclass();
        return distance;
    }
}

Related

  1. newInstance(Class type)
  2. newInstance(Class type)
  3. newInstance(Class type)
  4. newInstance(Class type)
  5. newInstance(Class type)
  6. newInstance(Class type)
  7. newInstance(Class type)
  8. newInstance(Class type, Class declarator, Annotation annotation)
  9. newInstance(Class type, Class[] parameterTypes, Object[] args)