Sì, perché entra in gioco l'auto-unboxing (da Java 5).
Se leggi qui sul JLS: 5.6.2. Binary Numeric Promotion
vedi che il primo punto è proprio l'unboxing, se necessario. Poi, dopo, il secondo punto è la catena di regole "se uno dei due operandi è un double, l'altro è convertito a double" ecc....
Ci sono un po' di regole .... potrei anche cercare di dirtele tutte (ammesso che io riesca a ricordarle tutte). La cosa importante da tenere a mente è che un cast cambia solo la "visione" del tipo statico del reference che vede il compilatore. Non cambia nulla nell'oggetto referenziato!
Qui il cast non serve affatto!
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
L'espressione Specifica.class (un class "literal") ha come tipo Class<Specifica>. Quindi il A è preso dal compilatore come Specifica, che è sicuramente una annotazione (noti che c'è un bound? solo ciò che è-un Annotation. Se Specifica non fosse una annotation, la tua riga non compilerebbe nemmeno!).
Siccome il tipo di ritorno è A e il compilatore "sa" che è Specifica, allora è tutto type-safe. Non c'è bisogno di cast.![]()