![](/img/trans.png)
[英]Java, how to check if one ParameterizedType represents a sub-type of another ParameterizedType?
[英]Javax Annotation Processing: Check if an annotated type is a sub-type of another type
我正在創建一個 AnnotationProcessor,我需要檢查帶注釋的類型是否是指定 class 的子類型。注釋:
public @interface Component {
Class<?> supertype();
}
示例:(正確)
@Component(supertype = MyInterface.class)
public class MyClass implements MyInterface {
// ...
}
示例:(不正確,這不能編譯,因為MyClass
不是String
的子類型)
@Component(supertype = String.class)
public class MyClass implements MyInterface {
}
我知道我無法獲得帶注釋的Class
,因為它尚未編譯。
您沒有在問題中提及它,但我假設您遇到了TypeMirror
問題。
這是獲取supertype
字段的TypeMirror
並將其與類型的基數 class 進行比較的非常古老且老套的解決方案:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeElement typeElement = (TypeElement) element;
Component componentAnnotation = typeElement.getAnnotation(Component.class);
TypeMirror superType = null;
try {
// Hack to quickly get to TypeMirror of the annotation property
componentAnnotation.supertype();
} catch (MirroredTypeException mte) {
superType = mte.getTypeMirror();
}
// TODO: superType null check
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
如果我是你,我會更深入地研究一下,看看現在是否有更好的選擇,但如果沒有,這將解決你的問題。
這個版本不依賴於異常,它使用Element.getAnnotationMirrors
,它可能用於此類用途。 雖然它更冗長:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeMirror superType = null;
boolean found = false;
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
TypeElement annotationElement = (TypeElement) mirror.getAnnotationType().asElement();
if (annotationElement.getQualifiedName().contentEquals(Component.class.getName())) {
found = true;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> kv :
mirror.getElementValues().entrySet()) {
ExecutableElement member = kv.getKey();
if (member.getKind() == ElementKind.METHOD &&
member.getSimpleName().contentEquals("supertype")) {
superType = (TypeMirror) kv.getValue().getValue();
break;
}
}
}
if (found) {
break;
}
}
// TODO: superType null check
TypeElement typeElement = (TypeElement) element;
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
使用如下代碼獲取注解中class值的TypeMirror
public Optional<TypeMirror> getClassValueFromAnnotation(Element element, Class<? extends Annotation> annotation, String paramName) {
for (AnnotationMirror am : element.getAnnotationMirrors()) {
if (types.isSameType(am.getAnnotationType(), elements.getTypeElement(annotation.getCanonicalName()).asType())) {
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am.getElementValues().entrySet()) {
if (paramName.equals(entry.getKey().getSimpleName().toString())) {
AnnotationValue annotationValue = entry.getValue();
return Optional.of((DeclaredType) annotationValue.getValue());
}
}
}
}
return Optional.empty();
}
然后使用此代碼檢查它是否是特定 class 的超類型
/**
* A wrapper over {@link Types#isAssignable(TypeMirror, TypeMirror)} which will apply type erasure on the targetClass before calling the wrapped method.
*
* @param typeMirror a {@link javax.lang.model.type.TypeMirror} object.
* @param targetClass a {@link java.lang.Class} object.
* @return a boolean.
*/
public boolean isAssignableFrom(TypeMirror typeMirror, Class<?> targetClass) {
return types.isAssignable(typeMirror, types.erasure(elements.getTypeElement(targetClass.getCanonicalName()).asType()));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.