javadoc:(JDK9) TypeElement中查找指定方法(Method)对应的ExecutableElement对象

JDK9 javadoc API获取的源码注释结构化数据中,

  • TypeElement对应java.lang.Class
  • ExecutableElement对应java.lang.reflect.Methodjava.lang.reflect.Constructor
  • VariableElement对应java.lang.reflect.Field

但是,JDK 9并没有提供从Java反射类型到java Doc类型的互操作。如果要想在TypeElement中获取指定方法的的注释对象,就要自己实现这个查找功能。

本文介绍如何在TypeElement中查找指定方法(Method)对应的ExecutableElement对象

ElementFilter

javax.lang.model.util.ElementFilter提供了一系列类型过滤方法,可以在TypeElement中查找 指定类型的元素。

示例如下:

// 查找TypeElement中所有的方法的ExecutableElement
TypeElement classDoc;
List<ExecutableElement> list = ElementFilter.methodsIn(classDoc.getEnclosedElements());
// 查找TypeElement中所有的构造方法的ExecutableElement
TypeElement classDoc;
List<ExecutableElement> list = ElementFilter.constructorsIn(classDoc.getEnclosedElements());
// 查找TypeElement中所有的字段方法的VariableElement 
TypeElement classDoc;
List<VariableElement> list = ElementFilter.fieldsIn(classDoc.getEnclosedElements());

匹配方法签名

有了ElementFilter提供的过滤功能,我们现在可以获取到所有的方法的ExecutableElement对象。
下一步就要通过方法名和参数匹配最终精确得到方法的ExecutableElement

如果是匹配方法签名的match方法实现

	/**
	 * 如果两个类型字符串匹配,返回{@code true},否则返回{@code false}
	 * @param docType
	 * @param type
	 */
	private boolean equalType(TypeMirror docType,java.lang.reflect.Type type) {
		String typeName = TypeNames.getTypeName(type);
		return typeName.equals(docType.toString());
	}
	/**
	 * 检查两个方法对象的签名是否匹配<br>
	 * @param member
	 * @param doc
	 * @return 不匹配返回 {@code false} ,匹配返回 {@code true}
	 */
	private boolean match(Member member, Element doc) {
		if (!member.getName().equals(doc.getSimpleName().toString())){
			return false;
		}
		if(member instanceof Field) {
			return true;
		}
		java.lang.reflect.Type[] paramTypes;
		if(member instanceof Method){
			paramTypes = ((Method)member).getGenericParameterTypes();
		}else if(member instanceof Constructor<?>){
			paramTypes = ((Constructor<?>)member).getParameterTypes();
		}else{
			throw new IllegalArgumentException(String.format("INVALID member type %s,Method or Constructor required",member.getClass().getSimpleName()));
		}
		if(!(doc instanceof ExecutableElement)) {
			throw new IllegalArgumentException(String.format("INVALID doc type %s,ExecutableElement required",doc.getClass().getSimpleName()));
		}
		List<? extends VariableElement> parameters = ((ExecutableElement)doc).getParameters();
		if (paramTypes.length != parameters.size()) {
			return false;
		}
		for (int i = 0; i < paramTypes.length; ++i) {
			if(!equalType(parameters.get(i).asType(),paramTypes[i])) {
				return false;
			}
		}
		return true;
	}

findMember

如下是在上面的准备基础上最终实现的查找方法实现:

	/**
	 * 在{@link TypeElement}中查找与method匹配的{@link ExecutableElement}对象<br>
	 * 没找到匹配的对象则返回{@code null}
	 * @param classDoc
	 * @param member 
	 */
	private Element findMember(TypeElement classDoc,Member member) {
		if (null == classDoc || null == member){
			return null;
		}
		if(!equalType(classDoc.asType(),member.getDeclaringClass())) {
			return null;
		}
		if (member instanceof Field) {
			return ElementFilter.fieldsIn(classDoc.getEnclosedElements()).stream().filter(e -> match(member, e))
					.findFirst().orElse(null);
		} else if (member instanceof Method) {
			return ElementFilter.methodsIn(classDoc.getEnclosedElements()).stream().filter(e -> match(member, e))
					.findFirst().orElse(null);
		} else if (member instanceof Constructor<?>) {
			return ElementFilter.constructorsIn(classDoc.getEnclosedElements()).stream().filter(e -> match(member, e))
					.findFirst().orElse(null);
		} else {
			throw new IllegalArgumentException(String.format(
					"INVALID member type %s,Field,Method or Constructor required", member.getClass().getSimpleName()));
		}
	}

完整代码

完整代码参见码云仓库:https://gitee.com/l0km/javadocreader9/blob/master/src/main/java/gu/doc/ExtClassDoc.java

相关文章

《javadoc:jdk 9通过javadoc API读取java源码中的注释信息(comment)》
《javdoc:(JDK9)VISITOR模式遍历语法树(DocCommentTree)获取代码注释中的tag(@return,@param)对象》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值