Le bytecode Java est fortement typé et vérifié, ce qui implique que le code de l'appelant doit être compatible avec ce que retournera la méthode invoquée. Ainsi, même si la référence de méthode de l'appelant ne contenait pas le type de retour attendu, le code contenait toujours des hypothèses implicites, par ex. essayer de faire long
arithmétique avec le résultat indique que la méthode devrait retourner long
plutôt que Object
ou void
. Les références de méthode indiquant le type de retour attendu simplifient la vérification et rendent le processus entier plus efficace. Vous pouvez vérifier l'exactitude du code d'une méthode en utilisant les signatures de méthode attendues sans effectuer de liaison réelle. Lorsqu'une instruction d'invocation de méthode est finalement liée, il n'est pas nécessaire de vérifier le code exécutable, seules les signatures doivent correspondre. C'est pourquoi le code octet Java a été conçu de cette manière, même si le code source Java n'a pas pu définir de types de retour différents, au moins dans les versions antérieures. À partir de Java 5, les règles ne sont plus aussi strictes.
Tenir compte de l'interface suivante:
interface StringFunction<R> {
R apply(String input);
}
En raison de l'effacement de type, il aura une méthode Object apply(String input)
au niveau du code d'octets.
considèrent maintenant la classe de mise en œuvre suivante:
class Length implements StringFunction<Integer> {
public Integer apply(String input) {
return input.length();
}
}
Non seulement déclarer un type de retour plus précis a permis, il est en fait nécessaire par le langage Java en fonction du système de type générique, il hérite d'un méthode abstraite Integer apply(String)
de StringFunction<Integer>
.
Au niveau du code octet, il aura la méthode de mise en œuvre effective Integer apply(String)
ainsi qu'un pont méthode Object apply(String input)
remplir formellement le contrat du interface
au niveau du code octet et de déléguer à la méthode de mise en œuvre effective.
Depuis Generics permettent effectivement un rétrécissement du type de retour, il n'y avait aucune raison de le nier pour les méthodes non-génériques, par conséquent, Java permet que l'on appelle types de retour covariants depuis Java 5 ainsi:
class Base {
Object getValue() {
return null;
}
}
class Sub extends Base {
@Override String getValue() {
return "now a string";
}
}
il est donc possible de produire des classes ayant plusieurs méthodes avec les mêmes types de paramètres mais des types de retour différents, mais pas par surcharge.
Ces cas pourraient être traités alternativement, par ex. en définissant que les méthodes ne sont distinguées que par les types de paramètres et que leur type de retour doit être identique ou plus spécifique pour être compatible avec les types de retour covariant, ce qui impliquerait qu'une JVM doit résoudre tous les types de retour avec impatience d'une classe, pour vérifier si le type est vraiment plus spécifique. Et encore, il faudrait coder le type de retour pour établir un contrat approprié entre l'appelant et l'appelé.
Ne devrait-il pas déclencher une erreur si le type de retour est changé? Que se passe-t-il si vous attribuez le résultat d'une méthode à une bibliothèque mais que la bibliothèque est modifiée par la suite pour qu'elle renvoie un objet vide ou incompatible? –