Java tutorial
//package com.java2s; /* * Original work Copyright (c) 2005-2008, The Android Open Source Project * Modified work Copyright (c) 2013, rovo89 and Tungstwenty * Modified work Copyright (c) 2015, Alibaba Mobile Infrastructure (Android) Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.lang.reflect.Constructor; import java.util.HashMap; public class Main { private static final HashMap<String, Constructor<?>> constructorCache = new HashMap<String, Constructor<?>>(); public static Constructor<?> findConstructorBestMatch(Class<?> clazz, Class<?>... parameterTypes) { StringBuilder sb = new StringBuilder(clazz.getName()); sb.append(getParametersString(parameterTypes)); sb.append("#bestmatch"); String fullConstructorName = sb.toString(); if (constructorCache.containsKey(fullConstructorName)) { Constructor<?> constructor = constructorCache.get(fullConstructorName); if (constructor == null) throw new NoSuchMethodError(fullConstructorName); return constructor; } try { Constructor<?> constructor = findConstructorExact(clazz, parameterTypes); constructorCache.put(fullConstructorName, constructor); return constructor; } catch (NoSuchMethodError ignored) { } Constructor<?> bestMatch = null; Constructor<?>[] constructors = clazz.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { // compare name and parameters // if (ClassUtils.isAssignable(parameterTypes, constructor.getParameterTypes(), true)) { // // get accessible version of method // if (bestMatch == null || MemberUtils.compareParameterTypes( // constructor.getParameterTypes(), // bestMatch.getParameterTypes(), // parameterTypes) < 0) { // bestMatch = constructor; // } // } } if (bestMatch != null) { bestMatch.setAccessible(true); constructorCache.put(fullConstructorName, bestMatch); return bestMatch; } else { NoSuchMethodError e = new NoSuchMethodError(fullConstructorName); constructorCache.put(fullConstructorName, null); throw e; } } public static Constructor<?> findConstructorBestMatch(Class<?> clazz, Object... args) { return findConstructorBestMatch(clazz, getParameterTypes(args)); } public static Constructor<?> findConstructorBestMatch(Class<?> clazz, Class<?>[] parameterTypes, Object[] args) { Class<?>[] argsClasses = null; for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] != null) continue; if (argsClasses == null) argsClasses = getParameterTypes(args); parameterTypes[i] = argsClasses[i]; } return findConstructorBestMatch(clazz, parameterTypes); } private static String getParametersString(Class<?>... clazzes) { StringBuilder sb = new StringBuilder("("); boolean first = true; for (Class<?> clazz : clazzes) { if (first) first = false; else sb.append(","); if (clazz != null) sb.append(clazz.getCanonicalName()); else sb.append("null"); } sb.append(")"); return sb.toString(); } public static Constructor<?> findConstructorExact(Class<?> clazz, Class<?>... parameterTypes) { StringBuilder sb = new StringBuilder(clazz.getName()); sb.append(getParametersString(parameterTypes)); sb.append("#exact"); String fullConstructorName = sb.toString(); if (constructorCache.containsKey(fullConstructorName)) { Constructor<?> constructor = constructorCache.get(fullConstructorName); if (constructor == null) throw new NoSuchMethodError(fullConstructorName); return constructor; } try { Constructor<?> constructor = clazz.getDeclaredConstructor(parameterTypes); constructor.setAccessible(true); constructorCache.put(fullConstructorName, constructor); return constructor; } catch (NoSuchMethodException e) { constructorCache.put(fullConstructorName, null); throw new NoSuchMethodError(fullConstructorName); } } /** * Return an array with the classes of the given objects */ public static Class<?>[] getParameterTypes(Object... args) { Class<?>[] clazzes = new Class<?>[args.length]; for (int i = 0; i < args.length; i++) { clazzes[i] = (args[i] != null) ? args[i].getClass() : null; } return clazzes; } }