I needed to dynamically load and instantiate some classes from a generated jar and a generated .class file which depends on that jar. So I came up with this:

```java
package ytm.yajco.translation.util;

import org.jetbrains.annotations.NotNull;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;

import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;

public class DynamicClass {
	protected static final StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
	protected final        Class<?>    loadedClass;

	/**
	 * <b>WARNING:</b> Do not call this constructor if {@code jar} has already been loaded.
	 * This will avoid multiple class loading.
	 * <p>
	 * Creates a new class loader which can load classes from {@code jar}.
	 * The new classloader inherits the classpath from the class loader of the caller of this constructor.
	 * Finally, the sought class is loaded from the given {@code jar}.
	 *
	 * @param classFQN fully qualified name of the class to be loaded
	 * @param jar      path to the jar or root directory where {@code classFQN} is to be found
	 * @see StackWalker#getCallerClass()
	 */
	public DynamicClass(String classFQN, @NotNull Path jar) throws MalformedURLException, ReflectiveOperationException {
		this(classFQN, jar, walker.getCallerClass().getClassLoader());
	}

	/**
	 * <b>WARNING:</b> Do not call this constructor if {@code jar} has already been loaded by {@code parentCL}
	 * or its ancestors. This will avoid multiple class loading.
	 * <p>
	 * Creates a new class loader which can load classes from {@code jar}.
	 * The new classloader inherits the classpath from {@code parentCL}.
	 * Finally, the sought class is loaded from the given {@code jar}.
	 *
	 * @param classFQN fully qualified name of the class to be loaded
	 * @param jar      path to the jar or root directory where {@code classFQN} is to be found
	 * @param parentCL classloader to use as a parent
	 */
	public DynamicClass(String classFQN, @NotNull Path jar, ClassLoader parentCL) throws MalformedURLException, ClassNotFoundException {
		final URL[] jarLocation = {jar.toUri().toURL()};
		final URLClassLoader classLoader = URLClassLoader.newInstance(jarLocation, parentCL);
		loadedClass = Class.forName(classFQN, true, classLoader);
	}

	/**
	 * Finds the sought class using the given class loader.
	 *
	 * @param classFQN    fully qualified name of the class to be loaded
	 * @param classLoader class loader to reuse
	 * @throws ClassNotFoundException if the class cannot be located by the specified class loader
	 */
	public DynamicClass(String classFQN, ClassLoader classLoader) throws ClassNotFoundException {
		loadedClass = Class.forName(classFQN, true, classLoader);
	}

	public Class<?> getLoadedClass() {
		return loadedClass;
	}

	public ClassLoader getClassLoader() {
		return loadedClass.getClassLoader();
	}
}

```

In one of the cases I know the interface statically so in my `DynamicSupplier` subclass:
```java
public Supplier<?> newSupplierInstance() throws ReflectiveOperationException {
	return (Supplier<?>) loadedClass.getDeclaredConstructor().newInstance();
}
```

In the other case I know the method signatures, so I have provided methods to which hide the reflective access. Also I wrap the new instance in a small class (maybe an adapter?) just to put an abstract layer when working with a bare `Object`.
```java
package ytm.yajco.translation.language;

import org.jetbrains.annotations.NotNull;
import ytm.yajco.translation.util.DynamicClass;

import java.io.Reader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.nio.file.Path;

public class DynamicParser extends DynamicClass {

// skipped JavaDoc for brevity in this review
	public DynamicParser(String parserFQN, @NotNull Path parserJar) throws MalformedURLException, ReflectiveOperationException {
		this(parserFQN, parserJar, walker.getCallerClass().getClassLoader());
	}

// skipped other constructors matching super for brevity in this review


	public static Object parseSentence(@NotNull Object parser, String sentence) throws ReflectiveOperationException {
		final Method parse = parser.getClass().getMethod("parse", String.class);
		return parse.invoke(parser, sentence);
	}

	public static Object parseSentence(@NotNull Object parser, Reader sentence) throws ReflectiveOperationException {
		final Method parse = parser.getClass().getMethod("parse", Reader.class);
		return parse.invoke(parser, sentence);
	}


	public Parser newParserInstance() throws ReflectiveOperationException {
		final Object parser = loadedClass.getDeclaredConstructor().newInstance();
		return new Parser(parser);
	}


	public static class Parser {
		private final Object parser;

		private Parser(Object parser) {
			this.parser = parser;
		}

		public Object parseSentence(String sentence) throws ReflectiveOperationException {
			return DynamicParser.parseSentence(parser, sentence);
		}

		public Object parseSentence(Reader sentence) throws ReflectiveOperationException {
			return DynamicParser.parseSentence(parser, sentence);
		}

		public Object getRealParser() {
			return parser;
		}
	}

}
```

So what do you think about my creation? :)