If you compile it with -Xlint
you'll get a warning:
c:\Users\Jon\Test>javac -Xlint SneakyThrow.java
SneakyThrow.java:9: warning: [unchecked] unchecked cast
throw (T) ex;
^
required: T
found: Throwable
where T is a type-variable:
T extends Throwable declared in method <T>sneakyThrowInner(Throwable)
1 warning
That's basically saying "This cast isn't really checked at execution time" (due to type erasure) - so the compiler reluctantly assumes you're doing the right thing, knowing that it won't actually be checked.
Now it's only the compiler which cares about checked and unchecked exceptions - it's not part of the JVM at all. So once you've got past the compiler, you're home free.
I'd strongly advise you to avoid doing this though.
In many cases there's a "real" check when you're using generics because something uses the desired type - but that's not always the case. For example:
List<String> strings = new ArrayList<String>();
List raw = strings;
raw.add(new Object()); // Haha! I've put a non-String in a List<String>!
Object x = strings.get(0); // This doesn't need a cast, so no exception...