This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
package org.redkale.convert;
|
||||
|
||||
import java.beans.*;
|
||||
import static org.redkale.convert.ObjectEncoder.TYPEZERO;
|
||||
import org.redkale.util.Creator;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Arrays;
|
||||
@@ -66,8 +65,6 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
||||
} else {
|
||||
clazz = (Class) type;
|
||||
}
|
||||
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
|
||||
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : TYPEZERO;
|
||||
this.creator = factory.loadCreator(clazz);
|
||||
|
||||
final Set<DeMember> list = new HashSet();
|
||||
@@ -78,7 +75,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
ref = factory.findRef(field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = ObjectEncoder.makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
|
||||
Type t = ObjectEncoder.createClassType(field.getGenericType(), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
|
||||
}
|
||||
final boolean reversible = factory.isReversible();
|
||||
@@ -100,7 +97,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
||||
}
|
||||
ref = factory.findRef(method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = ObjectEncoder.makeGenericType(method.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
|
||||
Type t = ObjectEncoder.createClassType(method.getGenericParameterTypes()[0], this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
|
||||
}
|
||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
||||
@@ -116,19 +113,19 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
||||
//不存在setter方法
|
||||
try {
|
||||
Field f = clazz.getDeclaredField(constructorField);
|
||||
Type t = ObjectEncoder.makeGenericType(f.getGenericType(), virGenericTypes, realGenericTypes);
|
||||
Type t = ObjectEncoder.createClassType(f.getGenericType(), this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
|
||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||
char[] fs = constructorField.toCharArray();
|
||||
fs[0] = Character.toUpperCase(fs[0]);
|
||||
String mn = new String(fs);
|
||||
Method getter = null;
|
||||
Method getter;
|
||||
try {
|
||||
getter = clazz.getMethod("get" + mn);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
getter = clazz.getMethod("is" + mn);
|
||||
}
|
||||
Type t = ObjectEncoder.makeGenericType(getter.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
|
||||
Type t = ObjectEncoder.createClassType(getter.getGenericParameterTypes()[0], this.type);
|
||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,53 +46,178 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
||||
this.members = new EnMember[0];
|
||||
}
|
||||
|
||||
static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||
if (type instanceof Class) {
|
||||
return type;
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
Type[] paramTypes = pt.getActualTypeArguments();
|
||||
final Type[] newTypes = new Type[paramTypes.length];
|
||||
int count = 0;
|
||||
for (int i = 0; i < newTypes.length; i++) {
|
||||
newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
||||
if (paramTypes[i] == newTypes[i]) count++;
|
||||
public void init(final Factory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) return;
|
||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||
final Class clazz = this.typeClass;
|
||||
final Set<EnMember> list = new HashSet();
|
||||
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
ref = factory.findRef(field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = createClassType(field.getGenericType(), this.type);
|
||||
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
||||
}
|
||||
final boolean reversible = factory.isReversible();
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getName().length() < 3) continue;
|
||||
if (method.getName().equals("getClass")) continue;
|
||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
|
||||
if (method.getParameterTypes().length != 0) continue;
|
||||
if (method.getReturnType() == void.class) continue;
|
||||
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
|
||||
boolean is = method.getName().startsWith("is");
|
||||
try {
|
||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = createClassType(method.getGenericReturnType(), this.type);
|
||||
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
||||
}
|
||||
this.members = list.toArray(new EnMember[list.size()]);
|
||||
Arrays.sort(this.members);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException(ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
if (count == paramTypes.length) return pt;
|
||||
return new ParameterizedType() {
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return newTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return pt.getRawType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return pt.getOwnerType();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
if (realGenericTypes == null) return type;
|
||||
if (type instanceof WildcardType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void convertTo(W out, T value) {
|
||||
if (value == null) {
|
||||
out.wirteClassName(null);
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != null && value.getClass() != this.typeClass) {
|
||||
final Class clz = value.getClass();
|
||||
out.wirteClassName(factory.getEntity(clz));
|
||||
factory.loadEncoder(clz).convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
out.writeObjectB(members.length, value);
|
||||
boolean comma = false;
|
||||
for (EnMember member : members) {
|
||||
comma = member.write(out, comma, value);
|
||||
}
|
||||
out.writeObjectE(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
|
||||
static Type createClassType(final Type type, final Type declaringType) {
|
||||
if (TypeToken.isClassType(type)) return type;
|
||||
//存在通配符则declaringType 必须是 ParameterizedType
|
||||
if (!(declaringType instanceof ParameterizedType)) return Object.class;
|
||||
if (type instanceof ParameterizedType) { // e.g. Map<String, String>
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
final Type[] paramTypes = pt.getActualTypeArguments();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
paramTypes[i] = createClassType(paramTypes[i], declaringType);
|
||||
}
|
||||
return TypeToken.createParameterizedType(pt.getOwnerType(), pt.getRawType(), paramTypes);
|
||||
}
|
||||
|
||||
final ParameterizedType declaringPType = (ParameterizedType) declaringType;
|
||||
final Type[] virTypes = ((Class) declaringPType.getRawType()).getTypeParameters();
|
||||
final Type[] desTypes = declaringPType.getActualTypeArguments();
|
||||
if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||
final WildcardType wt = (WildcardType) type;
|
||||
for (Type f : wt.getUpperBounds()) {
|
||||
for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
||||
for (int i = 0; i < virTypes.length; i++) {
|
||||
if (virTypes[i].equals(f)) return desTypes.length <= i ? Object.class : desTypes[i];
|
||||
}
|
||||
}
|
||||
} else if (type instanceof TypeVariable) {
|
||||
for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
||||
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||
for (int i = 0; i < virTypes.length; i++) {
|
||||
if (virTypes[i].equals(type)) return desTypes.length <= i ? Object.class : desTypes[i];
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
//
|
||||
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||
// if (type instanceof Class) { //e.g. String
|
||||
// return type;
|
||||
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
|
||||
// final ParameterizedType pt = (ParameterizedType) type;
|
||||
// Type[] paramTypes = pt.getActualTypeArguments();
|
||||
// final Type[] newTypes = new Type[paramTypes.length];
|
||||
// int count = 0;
|
||||
// for (int i = 0; i < newTypes.length; i++) {
|
||||
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
||||
// if (paramTypes[i] == newTypes[i]) count++;
|
||||
// }
|
||||
// if (count == paramTypes.length) return pt;
|
||||
// return new ParameterizedType() {
|
||||
//
|
||||
// @Override
|
||||
// public Type[] getActualTypeArguments() {
|
||||
// return newTypes;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getRawType() {
|
||||
// return pt.getRawType();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Type getOwnerType() {
|
||||
// return pt.getOwnerType();
|
||||
// }
|
||||
//
|
||||
// };
|
||||
// }
|
||||
// if (realGenericTypes == null) return type;
|
||||
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
||||
// final WildcardType wt = (WildcardType) type;
|
||||
// for (Type f : wt.getUpperBounds()) {
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
||||
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
||||
// }
|
||||
// }
|
||||
// return type;
|
||||
// }
|
||||
|
||||
static boolean contains(String[] values, String value) {
|
||||
for (String str : values) {
|
||||
@@ -151,102 +276,4 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
||||
return Attribute.create(clazz, fieldalias, field, getter, setter);
|
||||
}
|
||||
|
||||
public void init(final Factory factory) {
|
||||
this.factory = factory;
|
||||
try {
|
||||
if (type == Object.class) return;
|
||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||
final Class clazz = this.typeClass;
|
||||
final Set<EnMember> list = new HashSet();
|
||||
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
|
||||
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : null;
|
||||
if (realGenericTypes != null) {
|
||||
// println(type + "," + Arrays.toString(virGenericTypes) + ", " + Arrays.toString(realGenericTypes));
|
||||
}
|
||||
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
|
||||
try {
|
||||
ConvertColumnEntry ref;
|
||||
for (final Field field : clazz.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
ref = factory.findRef(field);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
|
||||
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
||||
}
|
||||
final boolean reversible = factory.isReversible();
|
||||
for (final Method method : clazz.getMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
if (method.getName().length() < 3) continue;
|
||||
if (method.getName().equals("getClass")) continue;
|
||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
|
||||
if (method.getParameterTypes().length != 0) continue;
|
||||
if (method.getReturnType() == void.class) continue;
|
||||
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
|
||||
boolean is = method.getName().startsWith("is");
|
||||
try {
|
||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ref = factory.findRef(method);
|
||||
if (ref != null && ref.ignore()) continue;
|
||||
Type t = makeGenericType(method.getGenericReturnType(), virGenericTypes, realGenericTypes);
|
||||
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
||||
}
|
||||
this.members = list.toArray(new EnMember[list.size()]);
|
||||
Arrays.sort(this.members);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new ConvertException(ex);
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void convertTo(W out, T value) {
|
||||
if (value == null) {
|
||||
out.wirteClassName(null);
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != null && value.getClass() != this.typeClass) {
|
||||
final Class clz = value.getClass();
|
||||
out.wirteClassName(factory.getEntity(clz));
|
||||
factory.loadEncoder(clz).convertTo(out, value);
|
||||
return;
|
||||
}
|
||||
out.writeObjectB(members.length, value);
|
||||
boolean comma = false;
|
||||
for (EnMember member : members) {
|
||||
comma = member.write(out, comma, value);
|
||||
}
|
||||
out.writeObjectE(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
*/
|
||||
package org.redkale.util;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -29,7 +30,107 @@ public abstract class TypeToken<T> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static Type createParameterizedType(final Type ownerType, final Type rawType, final Type... actualTypeArguments) {
|
||||
/**
|
||||
* 判断Type是否能确定最终的class, 是则返回true,存在通配符或者不确定类型则返回false。
|
||||
* 例如: Map< String, String > 返回 ture; Map< ? extends Serializable, String > 返回false;
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public final static boolean isClassType(final Type type) {
|
||||
if (type instanceof Class) return true;
|
||||
if (type instanceof WildcardType) return false;
|
||||
if (type instanceof TypeVariable) return false;
|
||||
if (type instanceof GenericArrayType) return isClassType(((GenericArrayType) type).getGenericComponentType());
|
||||
if (!(type instanceof ParameterizedType)) return false; //只能是null了
|
||||
final ParameterizedType ptype = (ParameterizedType) type;
|
||||
if (ptype.getOwnerType() != null && !isClassType(ptype.getOwnerType())) return false;
|
||||
if (!isClassType(ptype.getRawType())) return false;
|
||||
for (Type t : ptype.getActualTypeArguments()) {
|
||||
if (!isClassType(t)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态创建 ParameterizedType
|
||||
*
|
||||
* @param ownerType0
|
||||
* @param rawType0
|
||||
* @param actualTypeArguments0
|
||||
* @return
|
||||
*/
|
||||
public static Type createParameterizedType(final Type ownerType0, final Type rawType0, final Type... actualTypeArguments0) {
|
||||
if (ownerType0 == null && rawType0 instanceof Class) {
|
||||
final Class[] actualClassArguments = new Class[actualTypeArguments0.length];
|
||||
int count = 0;
|
||||
for (int i = 0; i < actualTypeArguments0.length; i++) {
|
||||
if (actualTypeArguments0[i] instanceof Class) {
|
||||
actualClassArguments[i] = (Class) actualTypeArguments0[i];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == actualClassArguments.length) return createParameterizedType((Class) rawType0, actualClassArguments);
|
||||
}
|
||||
return new ParameterizedType() {
|
||||
private final Class<?> rawType = (Class<?>) rawType0;
|
||||
|
||||
private final Type ownerType = ownerType0;
|
||||
|
||||
private final Type[] argTypes = actualTypeArguments0;
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return argTypes.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return rawType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return ownerType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(argTypes) ^ Objects.hashCode(rawType) ^ Objects.hashCode(ownerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof ParameterizedType)) return false;
|
||||
final ParameterizedType that = (ParameterizedType) o;
|
||||
if (this == that) return true;
|
||||
return Objects.equals(ownerType, that.getOwnerType())
|
||||
&& Objects.equals(rawType, that.getRawType())
|
||||
&& Arrays.equals(argTypes, that.getActualTypeArguments());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (ownerType != null) sb.append((ownerType instanceof Class) ? (((Class) ownerType).getName()) : ownerType.toString()).append(".");
|
||||
sb.append(rawType.getName());
|
||||
|
||||
if (argTypes != null && argTypes.length > 0) {
|
||||
sb.append("<");
|
||||
boolean first = true;
|
||||
for (Type t : argTypes) {
|
||||
if (!first) sb.append(", ");
|
||||
sb.append(t.getTypeName());
|
||||
first = false;
|
||||
}
|
||||
sb.append(">");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Type createParameterizedType(final Class rawType, final Class... actualTypeArguments) {
|
||||
ClassLoader loader = TypeToken.class.getClassLoader();
|
||||
String newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + System.currentTimeMillis();
|
||||
for (;;) {
|
||||
@@ -44,11 +145,11 @@ public abstract class TypeToken<T> {
|
||||
FieldVisitor fv;
|
||||
MethodVisitor mv;
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null);
|
||||
String rawTypeDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor((Class) rawType);
|
||||
String rawTypeDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(rawType);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(rawTypeDesc.substring(0, rawTypeDesc.length() - 1)).append('<');
|
||||
for (Type c : actualTypeArguments) {
|
||||
sb.append(jdk.internal.org.objectweb.asm.Type.getDescriptor((Class) c));
|
||||
for (Class c : actualTypeArguments) {
|
||||
sb.append(jdk.internal.org.objectweb.asm.Type.getDescriptor(c));
|
||||
}
|
||||
sb.append(">;");
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user