在java中需要一个默认构造函数? [英] Require a default constructor in java?

查看:200
本文介绍了在java中需要一个默认构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么方法可要求某个类具有默认(无参数)构造函数, aside 无法使用如下所示的反射检查?

Is there any way to require that a class have a default (no parameter) constructor, aside from using a reflection check like the following? (the following would work, but it's hacky and reflection is slow)

 boolean valid = false;
 for(Constructor<?> c : TParse.class.getConstructors())
 {
   if(c.getParameterTypes().length == 0) {
      valid = true;
      break; 
   }
 }
 if(!valid)
    throw new MissingDefaultConstructorException(...);


推荐答案

您可以为此构建注释处理器。注释处理器是在编译时运行的编译器插件。他们的错误显示为编译器错误,甚至可能会停止构建。

You can build an Annotation processor for that. Annotation Processors are compiler plugins that get run at compile time. Their errors show up as compiler errors, and may even halt the build.

这是一个示例代码(我没有运行它):

Here is a sample code (I didn't run it though):

@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");
    }

}

注释处理器变得更加容易if (例如RequiresDefaultAnnotation)。

The annotation processor becomes even easier if you introduce an annotation (e.g. RequiresDefaultAnnotation).

声明具有默认限定符的要求

::我还假设OP要求一个机制,防止开发人员,特别是由别人写的错误。::

::I am also assuming that the OP asking for a mechanism that prevents accidental errors for developers, especially written by someone else.::

是一种声明哪些类需要默认处理器的机制。希望你已经有了一个标准,无论它是名称中的模式,限定符中的模式,可能的注释和/或基本类型。在上面提供的示例中,您可以在方法 requiresDefaultConstructor()中指定条件。下面是一个如何做的示例:

There has to be a mechanism to declare which classes require a default processor. Hopefully, you already have a criteria for that, whether it is a pattern in the name, pattern in the qualifier, a possible annotation, and/or a base type. In the sample I provided above, you can specify the criteria in the method requiresDefaultConstructor(). Here is a sample of how it can be done:


  1. 基于名称模式。 TypeElement 提供对完全限定名称和程序包名称的访问。

  1. Based on a name pattern. TypeElement provide access to the fully qualified name and package name.

return type.getQualifiedName().toString().contains("POJO");


  • 基于类型声明上的注释。例如,所有的Java Bean Entity类都应该有一个非默认的构造函数。

  • Based on an annotation present on the type declaration. For example, all Java Bean Entity classes should have a non-default constructors

    return type.getAnnotation(Entity.class) != null;
    


  • 基于抽象类或接口。

  • Based on a abstract class or interface.

    TypeElement basetype = processingEnv.getElements().getTypeElement("com.notnoop.mybase");
    return processingEnv.getTypes().isSubtype(type.asType(), basetype.asType());
    


  • [推荐方法]:如果您使用的是基类型界面,方法与基类型接口。您可以声明注释,例如 MyPlain 以及元注释: @Inherited 。然后,您可以用该注释注释基类型,所有子类也将继承注释。那么你的方法只是

  • [Recommended Approach]: If you are using the basetype interface, I recommend mixing the annotation approach with the base type interface. You can declare an annotation, e.g. MyPlain, along with the meta annotation: @Inherited. Then you can annotate the base type with that annotation, then all subclasses would inherit the annotation as well. Then your method would just be

    return type.getAnnotation(MyPlain.class) != null;
    

    这更好,因为如果模式确实基于类型层次结构,

    This is better because it's a bit more configurable, if the pattern is indeed based on type hierarchy, and you own the root class.



    如上所述,只是因为它被称为注释处理你必须使用注释!您要跟踪的列表中的哪种方法取决于您的上下文。基本上,关键是,无论你想在部署执行工具中配置什么逻辑,该逻辑都会在 requiresDefaultConstructor 中。

    处理器将在上运行的类

    注释对任何给定类的处理器调用取决于 SupportedAnnotationTypes 。如果 SupportedAnnotationTypes 元注释指定了具体的注释,那么处理器将只运行在包含这样的注释的类上。

    Annotation Processors invocation on any given class depends on SupportedAnnotationTypes. If the SupportedAnnotationTypes meta-annotation specifies a concrete annotation, then the processor will only run on those classes that contain such annotation.

    如果 SupportedAnnotationTypes *,那么处理器将被调用所有类,注释或不!查看[Javadoc]( http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes()),其中说明:

    If SupportedAnnotationTypes is "*" though, then the processor will be invoked on all classes, annotated or not! Check out the [Javadoc](http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes()), which states:


    最后,*本身表示所有注释类型的
    集合,包括
    空集。注意处理器
    不应该声明*,除非它是
    实际处理所有文件;
    声明不必要的注释可能会使
    在某些
    环境中导致性能下降。

    Finally, "*" by itself represents the set of all annotation types, including the empty set. Note that a processor should not claim "*" unless it is actually processing all files; claiming unnecessary annotations may cause a performance slowdown in some environments.

    返回 false ,以确保处理器不声明所有注释。

    Please note how false is returned to ensure that the processor doesn't claim all annotations.

    这篇关于在java中需要一个默认构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆