Java 获取泛型类型的泛型参数
在某些背景下,我正在为我正在开发的编程语言(即JVM语言)编写一些框架材料,并使用Java类测试一些框架,因此下面所有奇怪的包装器Java 获取泛型类型的泛型参数,java,generics,reflection,nested-generics,Java,Generics,Reflection,Nested Generics,在某些背景下,我正在为我正在开发的编程语言(即JVM语言)编写一些框架材料,并使用Java类测试一些框架,因此下面所有奇怪的包装器 所以,我的问题是,如何获得类型参数边界的类型变量?目前我有以下几点: public static TemplateGenerics of(Class clazz) { TemplateGenerics generics = new TemplateGenerics(); //TemplateGenerics is a wrapper class for g
所以,我的问题是,如何获得类型参数边界的类型变量?目前我有以下几点:
public static TemplateGenerics of(Class clazz) {
TemplateGenerics generics = new TemplateGenerics(); //TemplateGenerics is a wrapper class for generics that appear in the class header
Stream.of(clazz.getTypeParameters()).forEach(typeVariable -> {
java.lang.reflect.Type b = typeVariable.getBounds()[0];
try {
Class c = Primitives.resolveClass(b.getTypeName().split("<", 2)[0]); //Is there a better way to do this?
TemplateGenerics sub = TemplateGenerics.of(c); //Recursivley get the generics - it fails here
generics.getConditionals().add(new Conditional(new Type.Hierarchical(sub, c.getName()), Conditional.Condition.EXTENDS, typeVariable.getName())); //Conditional is another wrapper class that handles bounds of the generic,
//Type.Hierachical is yet another wrapper class that wraps types that appear in class headers
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); //For testing purposes
}
});
return generics;
}
的公共静态模板泛型(类clazz){
TemplateGenerics generics=new TemplateGenerics();//TemplateGenerics是类标题中出现的泛型的包装类
Stream.of(clazz.getTypeParameters()).forEach(typeVariable->{
java.lang.reflect.Type b=typeVariable.getBounds()[0];
试一试{
Class c=Primitives.resolveClass(b.getTypeName().split(“@csharpfolk)正确地建议记录已解析的内容并利用这些内容。下面是一个可编译和可运行的示例,它演示了在实际中如何解决您的问题
package so.answers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public class TemplateGenerics {
private final List<Conditional> conditionals = new ArrayList<>();
public List<Conditional> getConditionals(){
return conditionals;
}
public String toString(){
return getConditionals().toString();
}
public static TemplateGenerics of(Class<?> clazz) {
return TemplateGenerics.of(clazz, new HashMap<>());
}
private static TemplateGenerics of(Class<?> clazz, Map<Class<?>, TemplateGenerics> existingGenericsForClasses) {
if(existingGenericsForClasses.containsKey(clazz)){
return existingGenericsForClasses.get(clazz);
}
final TemplateGenerics generics = new TemplateGenerics();
existingGenericsForClasses.put(clazz, generics);
Stream.of(clazz.getTypeParameters()).forEach(typeVariable -> {
java.lang.reflect.Type b = typeVariable.getBounds()[0];
try {
Class<?> c = Primitives.resolveClass(b.getTypeName().split("<", 2)[0]); //Is there a better way to do this?
TemplateGenerics sub = TemplateGenerics.of(c, existingGenericsForClasses); //Recursivley get the generics - it fails here
generics.getConditionals().add(new Conditional(new Type.Hierarchical(sub, c.getName()), Conditional.Condition.EXTENDS, typeVariable.getName())); //Conditional is another wrapper class that handles bounds of the generic,
//Type.Hierachical is yet another wrapper class that wraps types that appear in class headers
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); //For testing purposes
}
});
return generics;
}
public static class Conditional{
public static enum Condition{
EXTENDS,
SUPER
}
private final Type.Hierarchical hierarchical;
private final Condition condition;
private final String typeName;
public Conditional(Type.Hierarchical hierarchical, Condition condition, String typeName){
this.hierarchical = hierarchical;
this.condition = condition;
this.typeName = typeName;
}
public String toString(){
return "Conditional$typeName="+typeName+" "
+"Conditional$condition="+condition+" "
+"Conditional$hierarchical={"+hierarchical+"} ";
}
}
public static class Primitives{
public static Class<?> resolveClass(String name) throws ClassNotFoundException{
String trimmedName = name.replaceFirst(TemplateGenerics.class.getCanonicalName()+".", "");
//not sure why this nonsense with the trimmed name
//is necessary, but you seem to already have a better
//version of this method anyway
if(trimmedName.contains(TemplateGenerics.class.getCanonicalName())){
name = trimmedName;
}
return Primitives.class.getClassLoader().loadClass(name);
}
}
public static class Type{
public static class Hierarchical{
private TemplateGenerics generics;
private String name;
public Hierarchical(TemplateGenerics generics, String name){
this.generics = generics;
this.name = name;
}
private boolean printing;
public String toString(){
try{
if(!printing){
printing = true;
return "Hierarchical$name="+name+ " Hierarchical$generics=("+generics+")";
} else {
return "Hierarchical$name="+name;
}
} finally {
printing = false;
}
}
}
}
public static class B{
}
public static class C<T extends B>{
}
public static class A<T extends A<T>>{
}
public static class X<T extends Y>{
}
public static class Y<T extends X>{
}
public static void main(String[] args){
System.out.println("For A:"+TemplateGenerics.of(A.class));
System.out.println("For C:"+TemplateGenerics.of(C.class));
System.out.println("For X:"+TemplateGenerics.of(X.class));
}
}
你可以通过打印而不是直接打印泛型来减少打印,但是这显示了解决方案的所有显著特征。
你也应该考虑CASE <代码> A<代码> >代码> B/COM>。一般来说,为了避免循环,你应该保持已处理的和当前处理的类型。你开始处理但没有结束的计数器类型你应该使用一些占位符,然后在处理所有类型后,你应该用适当的结果替换占位符是的,我试着用地图做类似的事情,但我仍然不确定如何获得我需要的信息。非常感谢!这基本上与我结束的内容相同干得好。
For A:[Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$A Hierarchical$generics=([Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$A} ])} ]
For C:[Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$B Hierarchical$generics=([])} ]
For X:[Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$Y Hierarchical$generics=([Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$X Hierarchical$generics=([Conditional$typeName=T Conditional$condition=EXTENDS Conditional$hierarchical={Hierarchical$name=so.answers.TemplateGenerics$Y} ])} ])} ]