public static <T> T newInstance(String className, Class<T> returnType, Class<?> callerClass) {
        if (className == null || className.isEmpty() || returnType == null) {
            throw new IllegalArgumentException("Non-empty class name and return type are required");
        } else if (callerClass == null) {
            callerClass = returnType;
        }

        try {
            Class<?> clazz = Class.forName(className, false, callerClass.getClassLoader());
            if (!returnType.isAssignableFrom(clazz)) {
                throw new IllegalArgumentException(
                        format("Invalid %s class type. Input class should be a superclass of %s.", className,
                                returnType));
            }

            return returnType.cast(clazz.getConstructor().newInstance());
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException(format("Class %s is not found in the classpath.", className));
        } catch (IllegalAccessException | NoSuchMethodException e) {
            throw new IllegalArgumentException(
                    format("Class %s does not have a public constructor without any argument.", className));
        } catch (InstantiationException | InvocationTargetException e) {
            throw new IllegalArgumentException(format("Error while creating an %s class instance.", className), e);
        }
    }
Extracts parameters, usually key-value pairs, from the given query string.

@param query  non-empty query string
@param params mutable map for extracted parameters, a new {@link HashMap}
              will be created when it's null
@return map with extracted parameters, usually same as {@code params}
clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseUtils.java