2010-01-23 2 views
5

Nous savons que lorsque nous utilisons des objets dans l'instruction sysout (System.out.Println) en interne, c'est la méthode toString qui est appelée. et avec primitive, il imprime directement. mais quand nous utilisons tout type de classe wrapper d'objets est utilisé comme dire entier supposent suivantunboxing ou toString() est utilisé dans sysout dans java

 Integer i = new Integer(10) 
     System.out.Println(i); 

est-il toString() est responsable ou Unboxing impression?

+0

Je pense que ce serait seulement unbox dans les cas où int était la seule option. Comme il y a un println (Object), cela serait probablement appelé. –

+0

@gurukulki, mis à jour par la réponse espère que cela aide. –

Répondre

10

Une série de tests et le débogage rapide montre que print(Object) est invoquée, pas print(int).

Une bonne façon de vérifier est la suivante:

Integer val = null; 
System.out.print(val); 

Si ont été utilisés non la boxe, ce serait une NullPointerException. Cela ne se produit pas, cependant, il imprime la chaîne null, qui est la sortie de String.valueOf(Object) quand une valeur nulle est transmise.

Un autre aspect à garder à l'esprit est que PrintStream existait avant Java 5. Lorsque Autoboxing a été introduit en Java 5, il fallait s'assurer que tout code existant utilisant PrintStream n'aurait pas soudainement changé de comportement.Ainsi, tout code appelant print(Object) ne doit pas subitement changer de comportement pour appeler print(int) à la place, simplement à cause d'une nouvelle fonctionnalité de langage. La rétrocompatibilité doit toujours être maintenue.

+1

(+1) perspicace :) – Bozho

+1

C'est intéressant, mais est-ce concluant? Il pourrait y avoir un 'if' manipulant des nulls. –

+0

Un 'if' où? Il n'y a pas de magie ici, et décocher un null lancera * toujours * un NPE. – skaffman

4

Tout cela est antérieur à autoboxing, qui a été introduit en 1.5. Le code qui répond à ces questions - ou les documents API - n'a pas du tout changé pour 1.5+.

Fondamentalement, à la fin de la ligne est la méthode toString pour les non-primitives comme les instances de Integer. Donc, tout d'abord, avec les primitives, il y a un traitement différent pour chacune d'entre elles. Pour int, par exemple

Imprime un nombre entier. La chaîne produite par String.valueOf (int) est traduite en octets en fonction du codage de caractères par défaut de la plate-forme , et ces octets sont écrits exactement de la manière de la méthode write (int).

Mais pour les objets comme Integer, println appelle print qui:

Imprimer un objet. La chaîne produite par la méthode String.valueOf méthode (Object) est traduit en octets selon caractères par défaut de la plate-forme de codage et ces octets sont écrits exactement de la manière de l'écriture (int).

Alors qu'est-ce que valueOf utilise? C'est la réponse à votre question: pour Integer sa méthode toString est appelée. Ceci est de la documentation sur String.valueOf

si l'argument est nul, alors une chaîne égale à « null »; sinon, la valeur de obj.toString() est renvoyée.

+1

Qu'est-ce que vous voulez expliquer ici. Ma question est simple ToString() ou Unboxing? lequel est responsable? – GuruKulki

+0

fixer ma réponse maintenant pour éclaircir ça ... –

5

(...) mais quand nous utilisons tout type de classe wrapper d'objets est utilisé dire supposons entier comme suit

Integer i = new Integer(10) 
    System.out.println(i); 

est-il toString() est responsable de impression ou Unboxing ?

vous passez un Object à println il est donc évident que l'on appelle println(Object obj) qui écrit la sortie de String.valueOf(obj) qui appelle obj.toString() si obj n'est pas null. PS: Sans vouloir vous offenser, pourquoi ne regardez-vous pas les sources?

Mise à jour: J'ai peut-être manqué le point de la question (ce qui est trompeur dans sa forme actuelle si je peux). En fait, la question pourrait être:

(...) mais quand nous utilisons tout type de classe wrapper d'objets est utilisé dire supposons entier comme suit

Integer i = new Integer(10) 
    System.out.println(i); 

Quelle sera la méthode appelée: println(Object) ou println(int)?

Si c'est ce que la question concerne, alors la réponse se trouve bien sûr dans The Java Language Specification. Pour simplifier, la méthode appelée lors de l'exécution sera la méthode qui est déterminée lors de la compilation. Maintenant, comment le compilateur détermine-t-il la méthode qui sera invoquée? Eh bien, cela est expliqué dans la section 15.12 Method Invocation Expressions. Je ne vais pas couvrir tous les détails, la spécification le fait mieux que moi mais, fondamentalement, la première étape consiste à trouver la classe ou l'interface à rechercher, la seconde étape consiste à trouver toutes les méthodes applicables et ensuite de prendre les plus spécifiques méthode, la troisième étape consiste à vérifier si la méthode choisie est appropriée. Je vais me concentrer sur la 2ème étape (qui est la plus intéressante ici). Comme décrit dans la section 15.12.2 Compile-Time Step 2: Determine Method Signature:

Une méthode est applicable si elle est soit applicable par le sous-typage (§15.12.2.2), applicable par invocation de méthode conversion (§15.12.2.3), ou il est un procédé de arité mobile applicable (§15.12.2.4).

Le processus de détermination applicabilité commence en déterminant les méthodes potentiellement applicables (§15.12.2.1). Le reste du processus est divisé en trois phases.


Discussion

Le but de la division en phases est d'assurer la compatibilité avec les anciennes versions de la programmation Java langue.


la première phase (§15.12.2.2) effectue une surcharge de résolution sans permettant la boxe ou unboxing conversion , ou l'utilisation d'invocation de méthode des d'arité. Si aucune méthode applicable n'est trouvée au cours de cette phase , le traitement se poursuit à la seconde phase .


Discussion

Cela garantit que tous les appels étaient valides dans les anciennes versions de la langue ne sont pas considérés comme ambigus à la suite de l'introduction de méthodes variables de arity, implicite boxe et/ou unboxing.


la deuxième phase (§15.12.2.3) effectue une surcharge résolution tout en permettant à la boxe et unboxing, mais encore s'oppose à l'utilisation d'invocation de méthode des d'arité. Si aucune méthode applicable n'est trouvée pendant cette phase , le traitement continue à la troisième phase .


Discussion

Cela garantit qu'une méthode arité variable est jamais invoquée si une méthode arité fixe applicable existe.


La troisième phase (§15.12.2.4) permet la surcharge à combiner avec méthodes variables de arity, la boxe et unboxing.

décider si une méthode est applicable volonté, dans le cas des méthodes génériques (§8.4.4), exigent que les arguments de type réels soient déterminés. Les arguments de type réels peuvent être passés explicitement ou implicitement. Si ils sont passés implicitement, ils doivent être déduit (§15.12.2.7) des types des expressions d'argument.

Si plusieurs méthodes applicables ont été identifiés au cours de l'une des trois phases d'essais d'applicabilité, alors le plus spécifique est choisi, comme indiqué à la section §15.12.2.5. Voir les paragraphes suivants pour les détails .

Dans ce cas particulier, println(Obj) est applicable par le sous-typage (et println(int) serait applicable par la conversion d'invocation comme la boxe/unboxing est une conversion (§5.3)). Ainsi, le compilateur entrera le phase 1. Et si l'on regarde la dernière phrase:

Si aucune méthode applicable par sous-typage est trouvé, la recherche de méthodes applicables se poursuit avec la phase 2 (§15.12.2.3). Sinon, la méthode la plus spécifique (§15.12.2.5) est choisie parmi les méthodes qui sont applicables par sous-typage.

Ici, il n'y a pas d'autres méthodes applicables par le sous-typage donc c'est la fin, println(Object) sera appelée (et donc toString() sera appelé à répondre à la question initiale).

+0

J'ai eu un doute qu'il peut unbox et imprimer la primitive int – GuruKulki

+0

@Pascal: Ce n'est pas vraiment un problème d'API, cependant, il s'agit de savoir si le langage lui-même préfère unboxing à passant l'objet. – skaffman

+0

@skaffman, il s'agit d'un problème d'API et de la manière dont l'API String est spécifiée. Le comportement de la chaîne, étant un objet et non une primitive, est déterminé par l'API. –

Questions connexes