jdc*_*589 12 java constructor default
除了使用如下的反射检查之外,有没有办法要求类具有默认(无参数)构造函数?(以下是可行的,但它很hacky,反射很慢)
boolean valid = false;
for(Constructor<?> c : TParse.class.getConstructors())
{
if(c.getParameterTypes().length == 0) {
valid = true;
break;
}
}
if(!valid)
throw new MissingDefaultConstructorException(...);
Run Code Online (Sandbox Code Playgroud)
not*_*oop 22
您可以为此构建一个Annotation处理器.注释处理器是在编译时运行的编译器插件.它们的错误显示为编译器错误,甚至可能会停止构建.
这是一个示例代码(虽然我没有运行它):
@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");
}
}
Run Code Online (Sandbox Code Playgroud)
如果引入注释(例如RequiresDefaultAnnotation),注释处理器会变得更加容易.
声明要求具有默认限定符
::我还假设OP要求一种机制来防止开发人员意外错误,尤其是其他人写的.::
必须有一种机制来声明哪些类需要默认处理器.希望您已经有了一个标准,无论是名称中的模式,限定符中的模式,可能的注释和/或基本类型.在上面提供的示例中,您可以在方法中指定条件requiresDefaultConstructor().以下是如何完成的示例:
基于名称模式. TypeElement提供对完全限定名称和包名称的访问.
return type.getQualifiedName().toString().contains("POJO");
Run Code Online (Sandbox Code Playgroud)基于类型声明中的注释.例如,所有Java Bean实体类都应具有非默认构造函数
return type.getAnnotation(Entity.class) != null;
Run Code Online (Sandbox Code Playgroud)基于抽象类或接口.
TypeElement basetype = processingEnv.getElements().getTypeElement("com.notnoop.mybase");
return processingEnv.getTypes().isSubtype(type.asType(), basetype.asType());
Run Code Online (Sandbox Code Playgroud)[推荐方法]:如果您使用的是basetype接口,我建议将注释方法与基本类型接口混合使用.您可以声明注释,例如MyPlain,与元注释一起:@Inherited.然后,您可以使用该批注对基本类型进行批注,然后所有子类也将继承该批注.那你的方法就是这样
return type.getAnnotation(MyPlain.class) != null;
Run Code Online (Sandbox Code Playgroud)
这是更好的,因为它更具可配置性,如果模式确实基于类型层次结构,并且您拥有根类.
如前所述,仅仅因为它被称为"注释处理",它确实意味着你必须使用注释!您要遵循的列表中的哪种方法取决于您的上下文.基本上,重点是无论您希望在部署实施工具中配置什么逻辑,该逻辑都会进入requiresDefaultConstructor.
处理器将运行的类
任何给定类的注释处理器调用依赖于SupportedAnnotationTypes.如果SupportedAnnotationTypes元注释指定了具体注释,则处理器将仅在包含此类注释的那些类上运行.
如果SupportedAnnotationTypes是"*",那么将在所有类上调用处理器,注释或不注释!查看[Javadoc](http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes()),其中指出:
最后,
"*"它本身代表所有注释类型的集合,包括空集.请注意,处理器不应声明,"*"除非它实际处理所有文件; 声称不必要的注释可能会导致某些环境中的性能下降.
请注意如何false返回以确保处理器不会声明所有注释.
不可以.上面的检查可以更容易地重写为:
try {
MyClass.newInstance();
} catch (InstantiationException E) {
// no constructor
} catch (IllegalAccessException E) {
// constructor exists but is not accessible
?
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4682 次 |
| 最近记录: |