feat: support generate parameterized class

This commit is contained in:
金戟
2022-11-15 21:44:40 +08:00
parent f8501b0722
commit 5c8ef00fce
2 changed files with 35 additions and 27 deletions

View File

@@ -18,31 +18,16 @@ public class ConstructionUtil {
public static <T> T generateSubClassOf(Class<T> clazz) throws InstantiationException {
StringBuilder sourceCode = new StringBuilder();
sourceCode.append("package ").append(clazz.getPackage().getName()).append(";\n")
.append("public class ").append(getSubclassName(clazz))
.append(clazz.isInterface() ? " implements " : " extends ")
.append(getClassName(clazz))
.append(" {\n");
.append("public class ").append(getSubclassName(clazz));
appendTypeParameters(sourceCode, clazz.getTypeParameters(), true);
sourceCode.append(clazz.isInterface() ? " implements " : " extends ")
.append(getClassName(clazz));
appendTypeParameters(sourceCode, clazz.getTypeParameters(), false);
sourceCode.append(" {\n");
for (Method m : clazz.getMethods()) {
if (!Modifier.isStatic(m.getModifiers()) && !Modifier.isFinal(m.getModifiers())) {
sourceCode.append("\tpublic ");
TypeVariable<Method>[] typeParameters = m.getTypeParameters();
if (typeParameters.length > 0) {
sourceCode.append("<");
for (int i = 0; i < typeParameters.length; i++) {
sourceCode.append(typeParameters[i].getName()).append(" extends ");
Type[] bounds = typeParameters[i].getBounds();
for (int j = 0; j < bounds.length; j++) {
sourceCode.append(getClassName(bounds[j]));
if (j < bounds.length - 1) {
sourceCode.append(" & ");
}
}
if (i < typeParameters.length - 1) {
sourceCode.append(", ");
}
}
sourceCode.append("> ");
}
appendTypeParameters(sourceCode, m.getTypeParameters(), true);
sourceCode.append(getClassName(m.getGenericReturnType())).append(" ")
.append(m.getName()).append("(");
Type[] parameters = m.getGenericParameterTypes();
@@ -75,6 +60,29 @@ public class ConstructionUtil {
}
}
private static void appendTypeParameters(StringBuilder sourceCode, TypeVariable<?>[] typeParameters, boolean withScope) {
if (typeParameters.length > 0) {
sourceCode.append("<");
for (int i = 0; i < typeParameters.length; i++) {
sourceCode.append(typeParameters[i].getName());
if (withScope) {
sourceCode.append(" extends ");
Type[] bounds = typeParameters[i].getBounds();
for (int j = 0; j < bounds.length; j++) {
sourceCode.append(getClassName(bounds[j]));
if (j < bounds.length - 1) {
sourceCode.append(" & ");
}
}
}
if (i < typeParameters.length - 1) {
sourceCode.append(", ");
}
}
sourceCode.append("> ");
}
}
private static String getClassName(Type clazz) {
if (clazz instanceof Class) {
return ((Class<?>)clazz).getName().replace(DOLLAR, DOT);

View File

@@ -36,15 +36,15 @@ class ConstructionUtilTest {
public static abstract class AbstractClazz implements RealInterface {
@Override
public void noParameterMethod() {}
public abstract <T extends String> T getById(T id);
public abstract <T extends String> T getByName(T name);
public abstract String getByTags(List<? extends String> tags);
public static <T> T useless() { return null; }
}
public static abstract class ParameterizedClazz<T> extends AbstractClazz implements RealInterface, EmptyInterface {
public abstract int getById(T id);
public abstract int getByIds(List<T> id);
public abstract int getByMap(Map<String, T> m);
public static abstract class ParameterizedClazz<S extends String, P> extends AbstractClazz implements RealInterface, EmptyInterface {
public abstract S getById(S id);
public abstract S getByIds(List<S> ids);
public abstract P getByMap(Map<String, P> m);
}
@Test