com.github.azbh111.utils.java.reflect.GenericUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-java Show documentation
Show all versions of utils-java Show documentation
com.github.azbh111:utils-java
The newest version!
package com.github.azbh111.utils.java.reflect;
import com.github.azbh111.utils.java.reflect.model.MuttableGenericArrayType;
import com.github.azbh111.utils.java.reflect.model.MuttableParameterizedType;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
/**
*
* @author pyz
* @date 2019/4/15 10:59 PM
*/
public class GenericUtils {
/**
* 方法Class.getGenericSuperclass()只能获取父类的
* 本方法支持多层extends/implements
*
* 例: com.github.azbh111.utils.java.reflect.generic.GenericUtilsTest.getGenericSuperclass()
*
* @param from
* @param to
* @return
*/
public static ParameterizedType getGenericSuperclass(Class from, Class to) {
return resolve(from, new LinkedList(), 0, to);
}
/**
* 方法Class.getGenericSuperclass()只能获取父类的
* 本方法支持多层extends/implements
*
* 例: com.github.azbh111.utils.java.reflect.generic.GenericUtilsTest.getGenericSuperclass()
*
* @param from
* @param to
* @return
*/
public static ParameterizedType getGenericSuperclass(ParameterizedType from, Class to) {
LinkedList nodes = new LinkedList();
GenericNode node = new GenericNode();
node.setSource(from);
node.setBridges(((Class) from.getRawType()).getTypeParameters());
nodes.add(node);
return resolve((Class) from.getRawType(), nodes, 0, to);
}
public static Type replaceTypeVariable(Type target, String name, Type type) {
Type r = target;
if (target instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) target;
if (tv.getName().equals(name)) {
r = type;
}
} else if (target instanceof ParameterizedType) {
MuttableParameterizedType mpt;
if (target instanceof MuttableParameterizedType) {
mpt = (MuttableParameterizedType) target;
} else {
mpt = MuttableParameterizedType.of((ParameterizedType) target);
}
Type[] ts = mpt.getActualTypeArguments();
for (int i = 0; i < ts.length; i++) {
ts[i] = replaceTypeVariable(ts[i], name, type);
}
r = mpt;
} else if (target instanceof GenericArrayType) {
MuttableGenericArrayType mgat;
if (target instanceof MuttableGenericArrayType) {
mgat = (MuttableGenericArrayType) target;
} else {
mgat = MuttableGenericArrayType.of((GenericArrayType) target);
}
mgat.setGenericComponentType(replaceTypeVariable(mgat.getGenericComponentType(), name, type));
r = mgat;
}
return r;
}
private static ParameterizedType resolve(Class from, LinkedList stacks, int skip, Class to) {
if (from == to) {
return resolve(stacks, skip, to);
}
Class sc = from.getSuperclass();
Type gsc = from.getGenericSuperclass();
Class[] itfs = from.getInterfaces();
Type[] gitfs = from.getGenericInterfaces();
int size = itfs.length;
for (int i = -1; i < size; i++) {
Class superClass = i == -1 ? sc : itfs[i];
Type genericSuperClass = i == -1 ? gsc : gitfs[i];
if (superClass == null || genericSuperClass == null) {
continue;
}
if (to.isAssignableFrom(superClass)) {
TypeVariable[] tps = superClass.getTypeParameters();
if (tps == null || tps.length == 0 || !(genericSuperClass instanceof ParameterizedType)) {
ParameterizedType pt = resolve(superClass, stacks, stacks.size(), to);
if (pt != null) {
return pt;
}
} else {
GenericNode node = new GenericNode();
node.setSource((ParameterizedType) genericSuperClass);
node.setBridges(tps);
stacks.add(node);
ParameterizedType pt = resolve(superClass, stacks, 0, to);
if (pt != null) {
return pt;
}
}
}
}
return null;
}
private static ParameterizedType resolve(LinkedList stacks, int skip, Class to) {
MuttableParameterizedType target = new MuttableParameterizedType();
target.setRawType(to);
target.setActualTypeArguments(new Type[to.getTypeParameters().length]);
System.arraycopy(to.getTypeParameters(), 0, target.getActualTypeArguments(), 0, target.getActualTypeArguments().length);
resolve(stacks, skip, target);
return target;
}
private static void resolve(List nodes, int skip, MuttableParameterizedType target) {
ListIterator it = nodes.listIterator(nodes.size() - skip);
while (it.hasPrevious()) {
resolve(it.previous(), target);
}
}
private static void resolve(GenericNode node, MuttableParameterizedType target) {
TypeVariable[] bridges = node.getBridges();
Type[] sources = node.getSource().getActualTypeArguments();
for (int i = 0; i < node.getBridges().length; i++) {
replaceTypeVariable(target, bridges[i].getName(), sources[i]);
}
}
private static class GenericNode {
ParameterizedType source;
TypeVariable[] bridges;
public ParameterizedType getSource() {
return source;
}
public void setSource(ParameterizedType source) {
this.source = source;
}
public TypeVariable[] getBridges() {
return bridges;
}
public void setBridges(TypeVariable[] bridges) {
this.bridges = bridges;
}
public void setBridges(Type[] actualTypeArguments) {
}
}
}