You can see '@NonNull String' as a strict subclass of String. After all, any non-null String is definitely an 'instanceof' '@Nullable String', but any instanceof '@Nullable String' may not be an instance of '@NonNull String' (it wouldn't be if it was null, for example).
Looking at it that way, @Nullable and @NonNull are type information, and are therefore perfectly reasonable in interfaces. You are indicating to implementers that they may return null, and that they do not have to worry about input nulls, and you are indicating to callers that they must not pass in null, and that they should expect nulls out.
Of course, while this is all very reasonable, vanilla javac v1.6 certainly doesn't enforce any of these rules the way it enforces type safety for actual types. But one can dream, or one could use something like pmd or findbugs to take the job of verifying these annotations.
The @NonNull and @Nullable annotations aren't enough for a complete nullity typing system, though. I don't really know why JSR305 doesn't address this, but there's a third type: "@MaybeNull". It would show up inside of generics parameters; anywhere else it would have the same meaning as @Nullable.
public static void addIfNotNull(List<@MaybeNull T> list, @Nullable T item) {
if ( item != null ) list.add(item);
}
If the annotation on the first 'T' there is "@Nullable", then you could not pass non-null lists in, which would make for a rather useless API. On the other hand, if it was @NonNull, you could not pass a nullable list in. In practice, it doesn't matter what you move in there, it'll (A) never cause a NullPointerException, and (B) never violate the annotation. So, you need a way to express: I don't care if this particular 'T' is Nullable or not; I will null-check when I read from it, and I will never write nulls, so it doesn't matter.
The difference between @MaybeNull and @Nullable is analogous to the difference between '? extends Number' and 'Number' in generics. Outside of generics they mean the same thing, but in generics there's a difference.
So, don't keep your hopes up for a rigid typecheck anytime soon.
@Inherited only works for classes, but one would imagine something similar for annotated return types and annotated parameters.