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
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type)
- newInstance(Class type, Class> declarator, Annotation annotation)
- newInstance(Class type, Class>[] parameterTypes, Object[] args)