我们可以在实现接口时有一个“不覆盖具体方法......”编译时错误吗?

时间:2010-01-02 17:02:59

标签: java oop interface override compiler-errors

在实现接口时,我们可以使用“不会覆盖具体方法... ”编译时错误吗?

更清楚的一个例子:

我构建了一个包含接口的框架。要使用框架,开发人员需要实现一些接口。 但如果他们不覆盖equals(Object object)hashCode() Object方法,内部API逻辑就会被破坏!!

javadoc中提到的所有内容但是我希望在实现接口时不会覆盖某些混凝土时出现编译时错误或者运行时异常方法

4 个答案:

答案 0 :(得分:7)

Java附带了注释处理器功能,从Java 6开始:Source Code Analysis。 (从技术上讲,它是Java 5的一部分,但Java 6将其集成到编译器阶段而不是特殊工具)。 Sun提供此Getting Started guide

编译器在构建项目时会调用注释处理器,并且可能像编译器一样发出错误。这是一种比Java指定更多规则的简洁方法。

以下是一个可以执行所需检查的示例处理器:

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class CheckMethodOverride extends AbstractProcessor {
    // returns true if the class has a method with the specified method name
    // and specified number of parameters
    private static boolean hasMethod(TypeElement clazz, String methodName, int arity) {
        for (ExecutableElement method : 
                 ElementFilter.methodsIn(clazz.getEnclosedElements())) {
            if (method.getSimpleName().equals(methodName)
                    && method.getParameters().size() == arity)
                return true;
        }
        return false;
    }

    // the interface whose subclasses must override hashCode and equals
    TypeMirror interfaceToCheck;

    @Override
    public void init(ProcessingEnvironment env) {
        interfaceToCheck = env.getElementUtils().getTypeElement("com.notnoop.myinterface").asType();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnvironment) {
        for (TypeElement e :
            ElementFilter.typesIn(roundEnvironment.getRootElements())) {
            if (this.processingEnv.getTypeUtils()
                     .isSubtype(e.asType(), interfaceToCheck)
                && (!hasMethod(e, "equals", 0)
                    || !hasMethod(e, "hashCode", 0))) {
                processingEnv.getMessager().printMessage(Kind.ERROR,
                    "Class " + e + " doesn't override hashCode or equals", e);
            }
        }
        return true;
    }
}

注释处理器可以直接在编译器选项中指定(通过向编译器选项添加-processor com.notnoop.CheckMethodOverride),或者在类路径中添加META-INF/services文件,其中包含处理器的名称({{ 1}})。 forlder com.notnoop.CheckMethodOverride可以存在于项目的根源目录中(如果使用maven,则可以存在于资源目录中)。

这适用于任何命令行编译器。我不知道如何在IDE中激活它。

答案 1 :(得分:2)

你不能用接口做,但你可以用抽象类做到这一点。 E.g。

public interface Entity {
    //...
}

public abstract class AbstractEntity implements Entity {

    @Override
    public abstract boolean equals(Object other);

    @Override
    public abstract int hashCode();

}

并告诉开发人员在他们想要实现AbstractEntity时延长Entity

如果你真的想要强制执行规则,你需要进行某种运行时检查,比如Spring中的bean后处理器。

答案 2 :(得分:1)

我担心这是错误的地方。我们回答有关语言的问题,我们不会制作语言。

Sun制定了社区流程,您可以在其中提出改进建议或彻底的错误报告。如果你愿意,我可以把你链接起来。

我怀疑它不会完成。如果到现在为止它不被认为是一个好主意,它可能不会。

在短期内帮助您的东西可能是独立的样式检查程序。 CheckStyle浮现在脑海中,它可能是最大的名字,它是免费的啤酒,并提供丰富的选择。我怀疑,但我不确定,“没有实施hashCode()equals()也在那里。

答案 3 :(得分:1)

我只想到了一个可能的选择:

您的界面(或可能是抽象方法)可以指定方法(例如)equals2()hashCode2()。当然,这些对于接口的任何实现者都是强制性的。因此,您可以强制您的图书馆消费者编写某些内容

然后,与您的接口实现者一起工作的库类可以使用这些“自定义”函数作为“真实”函数的替换或实现,并重新定义自己。

这不是一个非常优雅的概念,并没有非常丰富,但你可以做出一些东西。