2017-05-09 1 views
2

On peut voir l'erreur:byte code Java et aucune erreur méthode

java.lang.NoSuchMethodError: com.nhn.user.UserAdmin.addUser(Ljava/lang/String;)V.

Cela dit que la méthode addUser sans type de retour ne se trouve pas. Cela peut être dû à la raison que, la bibliothèque peut être mise à jour, mais le code d'octet de notre application est encore vieux. Mais quand on étudie la surcharge Java, on peut savoir que Java ne supporte pas la surcharge avec seulement un changement de type de retour. Puisque c'est correct, pourquoi byte code noter le type de retour de la méthode appelée, et augmenter l'erreur quand la bibliothèque est mise à jour avec un type de retour pour la méthode.

+0

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? –

Répondre

0

La méthode peut avoir été déclarée dans une interface, puis surchargée. Ainsi, lorsque vous avez modifié la version implémentée de la méthode, cela a provoqué une erreur. Si le type de retour ne correspond pas, mais le nom est le même, une erreur persiste. La modification du type de retour ne peut pas être effectuée car le compilateur ne peut pas savoir quel type de retour vous souhaitez utiliser lorsque vous appelez la méthode.

+0

J'ai compris quelle est la raison de l'erreur, ma question est, quand nous ne pouvons pas surcharger une méthode, avec un changement uniquement dans le type de retour, pourquoi la JVM a enregistré les détails du type de retour de la méthode? Quelle est l'utilisation de stocker des informations de type de retour de la méthode. – Jobs

1

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é.

+0

c'est la deuxième fois que je lis une de vos réponses qui couvre la covariance. J'étais tout à fait sûr d'avoir compris ce que cela signifiait avant de les lire et garçon j'avais tort ... – Eugene

+0

@Eugene: J'aime vraiment [celui-ci] (http://stackoverflow.com/questions/2723397/what-is-pecs- producer-extends-consumer-super/19739576 # 19739576) pour expliquer la variance ... – Holger