@NonNull and similar annotations can and are used by static analyzer programs to completely eliminate null exceptions. For example Checker Framework can do that and much more.
This is the exact same thing that languages with null-safety have “in-built”. Sure, language support is nice, but it is here and is working
Optional is convention based and @NonNull just throws the runtime exception at a better location, so in my experience neither come remotely close to providing null safety.