代码之家  ›  专栏  ›  技术社区  ›  jdc0589

需要java中的默认构造函数吗?

  •  12
  • jdc0589  · 技术社区  · 16 年前

    要求 类具有默认(无参数)构造函数, 从使用反射检查,如下面? (以下方法可行,但它很粗糙,而且反射速度很慢)

     boolean valid = false;
     for(Constructor<?> c : TParse.class.getConstructors())
     {
       if(c.getParameterTypes().length == 0) {
          valid = true;
          break; 
       }
     }
     if(!valid)
        throw new MissingDefaultConstructorException(...);
    
    3 回复  |  直到 16 年前
        1
  •  23
  •   notnoop    16 年前

    @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() . 下面是一个如何实现的示例:

    1. 基于名称模式。 TypeElement

      return type.getQualifiedName().toString().contains("POJO");
      
    2. 基于类型声明上的注释。例如,所有JavaBean实体类都应该有一个非默认构造函数

      return type.getAnnotation(Entity.class) != null;
      
    3. 基于抽象类或接口。

      TypeElement basetype = processingEnv.getElements().getTypeElement("com.notnoop.mybase");
      return processingEnv.getTypes().isSubtype(type.asType(), basetype.asType());
      
    4. [推荐方法]:如果您使用的是基类型接口,我建议将注释方法与基类型接口混合使用。您可以声明注释,例如。 MyPlain ,以及元注释: @Inherited

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

      如果模式确实基于类型层次结构,并且您拥有根类,那么这会更好,因为它更易于配置。

    正如前面提到的,仅仅因为它被称为“注释处理”,它就意味着您必须使用注释!您希望遵循列表中的哪种方法取决于您的上下文。基本上,要点是,无论您希望在部署实施工具中配置什么逻辑,都会使用该逻辑 requiresDefaultConstructor .

    处理器将在其上运行的类

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

    如果 支持的注释类型 "*" 尽管如此,处理器将在所有类上调用,无论是否带注释!查看[Javadoc]( http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes())

    最后 "*" 它本身就代表了 所有注释类型的集合,包括 空位。请注意,处理器 不应要求 "*" 实际处理所有文件; 声明不必要的注释可能会 在某些情况下会导致性能下降 环境。

    请注意如何 false 返回以确保处理器不会声明所有批注。

        2
  •  6
  •   ChssPly76    16 年前

    否。上述检查可以更容易地重写为:

    try {
      MyClass.newInstance();
    } catch (InstantiationException E) {
      // no constructor
    } catch (IllegalAccessException E) {
      // constructor exists but is not accessible
    ?
    
        3
  •  1
  •   Richard Gomes    15 年前

    在第二部分中,Macker会引发编译错误,当验证失败时会中断构建过程。

    Macker扩展了PMD流行的一些关于源代码验证的概念。一个很好的例子是,当您希望保证包中的所有类都实现某个接口时。

    所以,如果你很偏执(像我一样!)关于验证所有可能的体系结构规则,Macker非常有用。

    http://innig.net/macker/

    注意:网站不是很好。颜色会伤害你的眼睛。。。但无论如何,这些工具都非常有用。

    理查德戈麦斯 http://www.jquantlib.org/