您可以为此构建一个注释处理器。注释处理器是在编译时运行的编译器插件。它们的错误显示为编译器错误,甚至可能会停止构建。
这是一个示例代码(虽然我没有运行它):
@SupportedAnnotationTypes("*") // needed to run on all classes being compiled
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class DefaultConstructor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (TypeElement type : ElementFilter.typesIn(roundEnv.getRootElements())) {
if (requiresDefaultConstructor(type))
checkForDefaultConstructor(type);
}
return false;
}
private void checkForDefaultConstructor(TypeElement type) {
for (ExecutableElement cons :
ElementFilter.constructorsIn(type.getEnclosedElements())) {
if (cons.getParameters().isEmpty())
return;
}
// Couldn't find any default constructor here
processingEnv.getMessager().printMessage(
Diagnostic.Kind.ERROR, "type is missing a default constructor",
type);
}
private boolean requiresDefaultConstructor(TypeElement type) {
// sample: require any JPA Entity to have a default constructor
return type.getAnnotation(Entity.class)) != null
|| type.getQualifiedName().toString().contains("POJO");
}
}
如果您引入注解(例如 RequiresDefaultAnnotation),注解处理器会变得更加容易。
声明具有默认限定符的要求
::我还假设 OP 要求一种机制来防止开发人员发生意外错误,尤其是由其他人编写的。::
必须有一种机制来声明哪些类需要默认处理器。希望您已经有了一个标准,无论是名称中的模式、限定符中的模式、可能的注释和/或基本类型。在我上面提供的示例中,您可以在方法requiresDefaultConstructor() 中指定条件。以下是如何完成的示例:
-
基于名称模式。 TypeElement 提供对完全限定名称和包名称的访问。
return type.getQualifiedName().toString().contains("POJO");
-
基于类型声明上的注释。例如,所有 Java Bean Entity 类都应该有一个非默认构造函数
return type.getAnnotation(Entity.class) != null;
-
基于抽象类或接口。
TypeElement basetype = processingEnv.getElements().getTypeElement("com.notnoop.mybase");
return processingEnv.getTypes().isSubtype(type.asType(), basetype.asType());
-
[推荐方法]:如果你使用的是基类型接口,我建议将注释方法与基类型接口混合使用。您可以声明一个注释,例如MyPlain,以及元注释:@Inherited。然后您可以使用该注释对基类型进行注释,然后所有子类也将继承该注释。那么你的方法就是
return type.getAnnotation(MyPlain.class) != null;
如果模式确实基于类型层次结构,并且您拥有根类,这会更好,因为它的可配置性更高。
前面说过,仅仅因为它叫做“注解处理”,就意味着你必须使用注解!您要遵循列表中的哪种方法取决于您的上下文。基本上,关键是无论您想在部署实施工具中配置什么逻辑,该逻辑都在requiresDefaultConstructor 中。
处理器将在其上运行的类
对任何给定类的注解处理器调用取决于SupportedAnnotationTypes。如果SupportedAnnotationTypes 元注解指定了具体注解,那么处理器将只在包含此类注解的类上运行。
如果SupportedAnnotationTypes 是"*",那么处理器将在所有类上调用,无论是否带注释!查看 [Javadoc](http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes()),其中指出:
最后,"*" 本身代表
所有注释类型的集合,包括
空集。请注意,处理器
不应声称"*",除非它是
实际处理所有文件;
声称不必要的注释可能
导致某些性能下降
环境。
请注意false 的返回方式,以确保处理器不会声明所有注释。