Java ships with annotation processor capabilities, starting from Java 6: Source Code Analysis. (Technically it's part of Java 5, but Java 6 integrated it into the compiler phase rather than a special tool). Sun provides this Getting Started guide.
An annotation processor gets invoked by the compiler while building the project, and may issue errors just like the compiler does. It's a neat way to enforce more rules than Java specifies.
Here is a sample Processor that would perform the check you desired:
@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;
}
}
The annotation processors can be specified directly in the compiler options (by adding -processor com.notnoop.CheckMethodOverride
to the compiler options), or adding a META-INF/services
file to your classpath which contains the name of the processor (com.notnoop.CheckMethodOverride
). The forlder META-INF
can live in the root source directory of the project (or resource directory if using maven).
This works with any command line compiler. I have no idea how to activate it in the IDEs though.