import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; public class AnnotationsAndMarkerInterfaces { public static void main(String[] args) { // Should we run this test? final Annotation theSlowTestAnnotation = ((Class) TestClass.class).getAnnotation(SlowTestAnnotation.class); if (theSlowTestAnnotation != null) { System.out.println(TestClass.class.getName() + " has the @SlowTestAnnotation. I don't want to run its tests."); } // Is there another reason not to run the tests? if (Arrays.stream(TestClass.class.getInterfaces()).anyMatch(interfaceClass -> interfaceClass == SlowTestMarkerInterface.class)) { System.out.println(TestClass.class.getName() + " implements SlowTestMarkerInterface. I don't want to run its tests."); } // If I gave you an instance of the test... final TestClass testClass = new TestClass(); // Would you run the tests? if (testClass instanceof SlowTestMarkerInterface) { System.out.println(testClass + " implements SlowTestMarkerInterface. I don't want to run its test!"); } // Heck; run the test anyway: testClass.run(); } } @Retention(RetentionPolicy.RUNTIME) @interface SlowTestAnnotation { } interface SlowTestMarkerInterface { } interface Test { void run(); } @SlowTestAnnotation class TestClass implements Test, SlowTestMarkerInterface { @Override public void run() { System.out.println("This test takes a long time to run!"); try { Thread.sleep(5000); } catch (final InterruptedException ex) { // (This is one of those rare cases where it's OK to throw away the exception.) } System.out.println("OK; I finished running this test."); } }