如何在Java中处理泛型;注释处理器";?
我之前问过一个“注释处理器”示例,它可以为接口生成代理/委托,但没有得到回答,在互联网上也没有找到任何东西,所以我自己做了一个 到目前为止,它工作得很好,直到我尝试在超级接口中使用泛型。如果我在带注释的界面中使用泛型,它工作得很好(更多的是出于偶然而不是设计)。但是,如果带注释的接口扩展了另一个采用泛型类型参数的接口,则该参数不会“绑定”到带注释的接口在扩展超级接口时使用的类型。例如:如何在Java中处理泛型;注释处理器";?,java,generics,annotations,Java,Generics,Annotations,我之前问过一个“注释处理器”示例,它可以为接口生成代理/委托,但没有得到回答,在互联网上也没有找到任何东西,所以我自己做了一个 到目前为止,它工作得很好,直到我尝试在超级接口中使用泛型。如果我在带注释的界面中使用泛型,它工作得很好(更多的是出于偶然而不是设计)。但是,如果带注释的接口扩展了另一个采用泛型类型参数的接口,则该参数不会“绑定”到带注释的接口在扩展超级接口时使用的类型。例如: public interface TestFragment<E> { void test(
public interface TestFragment<E> {
void test(E dummy);
}
@CreateWrapper
public interface TestService extends TestFragment<String> {
double myOwnMethod();
}
而不是正确的:
// ...
public void test(final String dummy) {
wrapped.test(dummy);
}
// ...
在生成的方法中生成参数的代码如下所示:
int count = 0;
for (VariableElement param : method.getParameters()) {
if (count > 0) {
pw.print(", ");
}
count++;
pw.printf("final %s %s", param.asType().toString(),
param.getSimpleName().toString());
}
有办法做到这一点吗?您需要的是替换,给定类型变量到类型参数的映射。在本例中,
E->String
。将任何类型中的任何E
替换为String
在javax.lang.model.util.Types
中没有这样的支持,您需要自己滚动。基本上
void print(TypeMirror type, Map<TypeVariable,TypeMirror> substitution)
if(substitution.containsKey(type)) // type is a var, E
print( substitution.get(type) ); // String
else if(type instanceof DeclaredType) // e.g. List<E>
print( type.asElement().getSimpleName() ); // List
for(TypeMirror arg : type.getTypeArguments() ) // E
print(arg, substitution)
etc. something like that
void打印(类型镜像类型,地图替换)
if(substitution.containsKey(type))//type是一个变量,E
打印(替换.获取(类型));//一串
else if(type instanceof DeclaredType)//例如List
打印(type.asElement().getSimpleName());//列表
for(TypeMirror arg:type.getTypeArguments())/E
打印(arg,替换)
诸如此类
看一看
可能会有帮助。我用它解决了一个非常类似的问题 复制粘贴我的:
这似乎是一个常见的问题,所以,对于那些来自谷歌的人来说:有希望
DI项目是根据Apache2.0许可证授权的,它包含一些用于在注释处理器中处理类型的实用方法
特别是,可以在GitHub()上完整查看Util
类,并定义一个方法公共静态字符串typeToString(TypeMirror类型)
。它使用TypeVisitor和一些递归调用来构建类型的字符串表示。以下是一个片段供参考:
public static void typeToString(final TypeMirror type, final StringBuilder result, final char innerClassSeparator)
{
type.accept(new SimpleTypeVisitor6<Void, Void>()
{
@Override
public Void visitDeclared(DeclaredType declaredType, Void v)
{
TypeElement typeElement = (TypeElement) declaredType.asElement();
rawTypeToString(result, typeElement, innerClassSeparator);
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (!typeArguments.isEmpty())
{
result.append("<");
for (int i = 0; i < typeArguments.size(); i++)
{
if (i != 0)
{
result.append(", ");
}
// NOTE: Recursively resolve the types
typeToString(typeArguments.get(i), result, innerClassSeparator);
}
result.append(">");
}
return null;
}
@Override
public Void visitPrimitive(PrimitiveType primitiveType, Void v) { ... }
@Override
public Void visitArray(ArrayType arrayType, Void v) { ... }
@Override
public Void visitTypeVariable(TypeVariable typeVariable, Void v)
{
result.append(typeVariable.asElement().getSimpleName());
return null;
}
@Override
public Void visitError(ErrorType errorType, Void v) { ... }
@Override
protected Void defaultAction(TypeMirror typeMirror, Void v) { ... }
}, null);
}
生成的源(当然是自定义的)。注意嵌套的泛型类型
public java.util.Set<AnnotationTest.B<java.lang.Integer>> AnnotationTest.A.getBsGenerated()
{
return this._bs;
}
public java.util.Set AnnotationTest.A.getBsGenerated()
{
把这个还给我;
}
编辑:调整概念以提取第一个泛型参数的TypeMirror,否则为null:
公共静态类型镜像getGenericType(最终类型镜像类型)
{
最终TypeMirror[]结果={null};
type.accept(新的SimpleTypeVisitor6()
{
@凌驾
公开无效访问声明(声明类型声明类型,无效v)
{
列表如果您按照Ryan Walls的建议使用
我恐怕是这样的。考虑到可能存在使用同一字母的多个泛型层的约束条件,您是否有任何建立这种映射的示例?(例如,列表)这应该标记为答案,因为它解决了问题。
public class AnnotationTest
{
...
public static class A
{
@MyAnnotation
private Set<B<Integer>> _bs;
}
public static class B<T>
{
private T _value;
}
}
accessor.type = DaggerUtils.typeToString(element.asType());
public java.util.Set<AnnotationTest.B<java.lang.Integer>> AnnotationTest.A.getBsGenerated()
{
return this._bs;
}
public static TypeMirror getGenericType(final TypeMirror type)
{
final TypeMirror[] result = { null };
type.accept(new SimpleTypeVisitor6<Void, Void>()
{
@Override
public Void visitDeclared(DeclaredType declaredType, Void v)
{
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (!typeArguments.isEmpty())
{
result[0] = typeArguments.get(0);
}
return null;
}
@Override
public Void visitPrimitive(PrimitiveType primitiveType, Void v)
{
return null;
}
@Override
public Void visitArray(ArrayType arrayType, Void v)
{
return null;
}
@Override
public Void visitTypeVariable(TypeVariable typeVariable, Void v)
{
return null;
}
@Override
public Void visitError(ErrorType errorType, Void v)
{
return null;
}
@Override
protected Void defaultAction(TypeMirror typeMirror, Void v)
{
throw new UnsupportedOperationException();
}
}, null);
return result[0];
}
ExecutableType methodType = (ExecutableType) typeUtil
.asMemberOf((DeclaredType) theAnnotatedClass.asType(), method);
int count = 0;
for (VariableElement param : method.getParameters()) {
if (count > 0) {
pw.print(", ");
}
TypeMirror actualParamType = methodType.getParameterTypes().get(count);
pw.printf("final %s %s", actualParamType.toString(),
param.getSimpleName().toString());
count++;
}