简体   繁体   中英

Java annotation for enforcing static variables or static methods?

I'm interested in doing something like this:

public interface Foo {

  public static "abstract" Bar SOME_BAR; // subclasses define one of these

}

and

public interface Foo {

  public static "abstract" Baz buildABas(...); // subclasses define this method 

}

without the statics, this is OOP 101, but it can't be done in standard oop java. I wonder if there's an annotation that would ensure this behavior?

edit:

i'm interested in specifying a set of options which define how to set things for "configurable" objects. this could be command-line flags, etc.

I'm guessing what you're wanting is to have a method like

public void callFoo(Class<?> clazz)

and you want to ensure that clazz has a method public static void foo() .

I thought about this a while and none of the techniques that come to mind will get you there. You can use an AnnotationProcessor to ensure that any classes annotated with a certain annotation have a specific method or what have you (and generate a compile error if they don't) but there's no way to ensure (at compile time) that Class arguments passed to callFoo(Class<?> clazz) are annotated with your annotation.

Here's an AnnotationProcessor that gets you halfway there:

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;


@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("so.Foo")
public class FooAnnotationProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {

        TypeElement foo = processingEnv.getElementUtils().getTypeElement("so.Foo");
        Set<? extends Element> classes = roundEnv.getElementsAnnotatedWith(foo);
        Messager messenger = processingEnv.getMessager();
        for (Element e : classes) {
            boolean found = false;
            for (Element method : e.getEnclosedElements()) {
                messenger.printMessage(Diagnostic.Kind.ERROR, 
                        method.getSimpleName());
                if (method.getKind() == ElementKind.METHOD && method.getSimpleName().toString().equals("getInstance")) {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                messenger.printMessage(Diagnostic.Kind.ERROR, 
                    "The following class does not implement getInstance : " + e.getSimpleName(),e);
            }
        }
        return true;
    }

}

Ultimately, I would suggest you either allow it to be something enforced at runtime or your redesign your code so you don't need to use static methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM