??最近樓主在使用APT寫(xiě)一個(gè)DI框架,這個(gè)框架主要是用于樓主的畢設(shè)項(xiàng)目中晌缘。但是在開(kāi)發(fā)這個(gè)框架時(shí)巍扛,遇到一個(gè)關(guān)鍵的問(wèn)題鬓长,就是調(diào)用Annotation
的方法來(lái)獲取一個(gè)Class
對(duì)象時(shí),結(jié)果在編譯時(shí)直接報(bào)錯(cuò)了巍糯,拋的異常就是MirroredTypeException
異常啸驯。本文的目的是解決這個(gè)問(wèn)題。
??本文參考資料:
1.提出問(wèn)題
??樓主自定義了一個(gè)Annotation
,這個(gè)Annotation
需要傳遞一個(gè)Class對(duì)象鳞贷。如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Container {
Class<?> value();
}
??然后坯汤,我在這個(gè)注解來(lái)標(biāo)記一個(gè)類(lèi),比如說(shuō)MainActivity
:
@Container(MainActivity.Context.class)
public class MainActivity extends AppCompatActivity {
@Inject
String string1;
@Inject("string")
String string2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class Context {
@Provides
String string1;
@Provides("string")
String string2;
}
}
??最后搀愧,再通過(guò)APT來(lái)掃描注解惰聂,拿到Container
注解的對(duì)象,進(jìn)而獲取它內(nèi)部的Class對(duì)象,也就是MainActivity.Context
的Class對(duì)象咱筛。一切都是那么的美好搓幌,但是現(xiàn)實(shí)的殘酷給我們當(dāng)頭一棒。就在我們開(kāi)心的build工程時(shí)迅箩,一個(gè)大大的異常出現(xiàn)我們的眼前--MirroredTypeException
溉愁。
??剛開(kāi)始出現(xiàn)這個(gè)異常時(shí),我是一臉懵逼的饲趋。當(dāng)時(shí)簡(jiǎn)單百度了一下拐揭,說(shuō)是該類(lèi)還未編譯撤蟆,不能獲取它的Class對(duì)象。說(shuō)句實(shí)話堂污,當(dāng)時(shí)非常的沮喪家肯,框架的大概結(jié)構(gòu)都已經(jīng)固定了,突然出現(xiàn)一個(gè)這個(gè)問(wèn)題盟猖,就意味著當(dāng)前這條路是不通的讨衣。
??不過(guò)好在天無(wú)絕人之路,我找到了解決方法式镐。
1. 解決問(wèn)題
??根據(jù) Getting Class values from Annotations in an AnnotationProcessor這篇文章反镇,可以找到兩種解決辦法。我們來(lái)看看娘汞,不過(guò)在看解決方法之前歹茶,我們還是先來(lái)看看之前,我們通過(guò)Annation
怎么獲取Class對(duì)象你弦。
Class<?> clazz = key.getAnnotation(Container.class).value();
??正常來(lái)說(shuō)辆亏,這一句是沒(méi)有毛病,可就是在編譯時(shí)會(huì)拋MirroredTypeException
異常鳖目,這也是本文需要解決的問(wèn)題“邕叮現(xiàn)在我們來(lái)看一下解決方案,一共有兩種领迈。
(1). 通過(guò)AnnotationMirrors來(lái)獲取
??從參看文章彻磁,我們首先可以找到第一種方法,就是通過(guò)AnnotationMirrors
來(lái)獲取狸捅。我們來(lái)看看代碼:
private String getClassFromAnnotation(Element key) {
List<? extends AnnotationMirror> annotationMirrors = key.getAnnotationMirrors();
for (AnnotationMirror annotationMirror : annotationMirrors) {
if (Container.class.getName().equals(annotationMirror.getAnnotationType().toString())) {
Set<? extends ExecutableElement> keySet = annotationMirror.getElementValues().keySet();
for (ExecutableElement executableElement : keySet) {
if (Objects.equals(executableElement.getSimpleName().toString(), "value")) {
return annotationMirror.getElementValues().get(executableElement).getValue().toString();
}
}
}
}
return null;
}
??上面的代碼我們能夠成功獲取這個(gè)Class
對(duì)象的name
字段衷蜓,更別說(shuō)Class
對(duì)象。其中annotationMirror.getElementValues().get(executableElement)
返回的是一個(gè)Object
對(duì)象尘喝,所以如果是Class<?>[]
類(lèi)型的話磁浇,可以直接進(jìn)行強(qiáng)轉(zhuǎn)。這里之所強(qiáng)調(diào)這一點(diǎn)朽褪,是跟第二種解決方案區(qū)別開(kāi)來(lái)置吓。
(2). 通過(guò)MirroredTypeException異常來(lái)獲取
??當(dāng)我們通過(guò)如上的方法獲取Class對(duì)象時(shí),會(huì)拋出MirroredTypeException
異常缔赠,我們可以根據(jù)MirroredTypeException
攜帶的相關(guān)信息來(lái)獲取我們想要的Class對(duì)象衍锚。
private String getClassFromAnnotationV2(Element key) {
try {
key.getAnnotation(Container.class).value();
} catch (MirroredTypeException e) {
TypeMirror typeMirror = e.getTypeMirror();
return typeMirror.toString();
}
return null;
}
??這種方法比較trick,但是不能否認(rèn)嗤堰,這也是一種解決方案戴质,而且比第一種方法更加的簡(jiǎn)單。這里需要的注意的是:
MirroredTypeException
不能獲取Class對(duì)象,只能獲取相應(yīng)的ClassName,其次它只能獲取Class對(duì)象的ClassName
告匠,而不能獲取Class數(shù)組對(duì)象的ClassName
戈抄,如果想要獲取Class數(shù)組對(duì)象的ClassName
,可以通過(guò)MirroredTypesException
來(lái)獲取后专。