2017-08-04 4 views
3

Lors de l'exploration de l'opérateur instanceof sur le niveau d'instruction d'assemblage du bytecode Java, cela correspond à une instruction d'assemblage Java instanceof. Mais je lis les règles utilisées pourQuelle est la signification des règles pour l'instruction d'assemblage Java instanceof?

déterminer si une ObjectRef qui est non nul est une instance de type résolu:

La deuxième règle dit:

Si S est un type d'interface, puis:

  • Si T est un type de classe, alors T doit être un objet.
  • Si T est un type d'interface, T doit être la même interface que S ou une superinterface de S.

Cela m'a fait confus. Est-ce que "S est un type d'interface" signifie que le type de référence de S est un type d'interface? si c'est le cas, la première règle "Si T est un type de classe, alors T doit un objet" ne peut pas être vrai. Par exemple,

CharSequence charSequence = new StringBuilder("test"); 
System.out.println(charSequence instanceof StringBuilder); 
System.out.println(charSequence instanceof String); 

la deuxième ligne dans le code ci-dessus serait vrai imprimer, alors que la troisième ligne serait au-dessus de l'impression fausse. Donc, je doute que ma compréhension est probablement fausse, n'importe qui peut aider à expliquer le sens de la règle ci-dessus?

+0

'S est la classe de l'objet référencé par * objectref *': dans ce cas, 'StringBuilder'. La troisième ligne d'impression 'false' est correcte. – EJP

+0

@EJP Mais ne pensez-vous pas que la première règle que j'ai mentionnée est différente de ce qui devrait être imprimé à partir du code que j'ai donné? String est Object, n'est-ce pas – Rui

Répondre

2

Vous avez le droit d'être confus, car la façon dont ces règles ont été écrites, sont déroutant.

Pour un ObjectRef, il est impossible d'avoir un type d'interface, comme chaque objet instancié a un type réel, non abstraite, peut-être la mise en œuvre d'une interface. Cela s'applique même aux instances générées pour les expressions lambda, qui ont un type (anonyme) non spécifié implémentant l'interface fonctionnelle.

Ainsi, au premier coup d'œil, il semble que cette partie de ces règles n'a pas de sens.Mais considérez le texte intégral:

Les règles suivantes sont utilisées pour déterminer si un ObjectRef qui ne null est une instance du type résolu: Si S est la classe de l'objet visé par ObjectRef et T est la classe résolu, tableau ou type d'interface, instanceof détermine si ObjectRef est une instance de T comme suit:

  • Si S est une classe ordinaire (nonarray), puis:
    • Si T est un type de classe, alors S doit être la même classe que T ou S doit être une sous-classe de T;
    • Si T est un type d'interface, alors S doit implémenter l'interface T.
  • Si S est un type d'interface, puis:
    • Si T est un type de classe, alors T doit être l'objet.
    • Si T est un type d'interface, alors T doit être la même interface que S ou une superinterface de S.
  • Si S est une classe représentant le type de tableau SC[], c'est un ensemble de composants de type SC, puis:
    • Si T est un type de classe, alors T doit être l'objet. Si T est un type d'interface, alors T doit être l'une des interfaces implémentées par les tableaux (JLS §4.10.3).
    • Si T est un type tableau TC[], qui est un ensemble de composants de type TC, puis une des options suivantes doivent être remplies:
      • TC et SC sont le même type primitif.
      • TC et SC sont des types de référence et le type SC peut être converti en TC par ces règles d'exécution.

Comme il est impossible pour l'objet réel référencé par ObjectRef avoir un type d'interface, seuls les deux autres balles sont applicables; son type est soit une "classe ordinaire (non-array)", soit un type tableau. Dans ce dernier cas, la dernière phrase est la plus intéressante, car elle renvoie aux règles citées dans leur ensemble, à appliquer aux types de composants T et S si les deux sont des tableaux d'un type de référence.Et le type de composant peut être un type d'interface.

Vous pouvez tester ces règles en utilisant une instance de tableau réel d'un type d'interface, la vérification par rapport aux autres types de tableau:

Object o = new Collection[0]; // SC is Collection 
System.out.println(o instanceof Object[]); // TC is class type Object -> true 
System.out.println(o instanceof String[]); // TC is class type other than Object -> false 
System.out.println(o instanceof Collection[]); // TC == SC -> true 
System.out.println(o instanceof Iterable[]); // TC is super interface of SC -> true 
System.out.println(o instanceof List[]); // TC is not super interface SC -> false 

Il pense, il serait moins confus, si le cas d'interface a été décrite dans le tableau spécial, où il peut s'appliquer. D'un autre côté, ces trois cas suivent les règles générales d'attribution formelles, de sorte qu'ils sont plus faciles à reconnaître sous cette forme.

+0

donc cela ne fonctionnerait que parce que les tableaux sont covariants non? Je ne peux pas penser à un seul endroit où j'ai vu un isntanceOf contre un tableau bien que – Eugene

+0

@Eugene: c'est une des règles qui * rendent * les tableaux covariants. – Holger