9
votes

Est-ce plus rapide d'appeler une méthode lors de l'initialisation d'un objet ou de la contenir comme une variable et d'appeler la méthode à ce sujet

En supposant qu'il existe une classe de classe qui donne une valeur dont j'ai besoin d'une méthode non statique.

Dans le cas où je n'ai que besoin d'une valeur d'une instance de la classe, Je suppose qu'il y a deux choix possibles. xxx

Je sais qu'il peut y avoir un avantage ou un désavantage pour les deux. Mais en général, quelle est la différence entre eux?

dans le cas 2), la consommation de mémoire est inférieure à 1) ou ....


3 commentaires

New Classa (HOGEHOGE) .GETVALUE; est une erreur de compilation!


Gardez toujours à l'esprit qu'il y a tellement d'optimisation effectuée dans le compilateur et dans la machine virtuelle afin que vous ne mesurez à peine aucune différence dans cet exemple.


Je comprends. Merci!


7 Réponses :


3
votes

différence est négligeable. Le premier cas conserve la référence A (4 octets) à la classea jusqu'à ce qu'il soit recueilli (par exemple, lorsque vous revenez de votre méthode).


1 commentaires

Cela peut être vrai si le code est interprété, mais dès qu'il est compilé au code natif de la JIT, il est très probable que la variable optimise l'éloignement, et il n'y aura aucune différence entre les deux versions.



10
votes

La seule différence est que dans la 2e cas, l'objet que vous avez créé sera admissible à la collection de déchets immédiatement après cette déclaration, car vous n'avez aucune référence à cet objet. Vous avez un objet sans nom là-bas.

tandis que dans le 1ère cas, car vous avez une référence à un objet, vous pouvez accéder à cet objet et son membre plus tard. Donc, il ne sera pas éligible pour Collection de déchets , [jusqu'à ce qu'il soit hors de portée] (cette déclaration, comme indiqué dans les commentaires ci-dessous, je suis toujours confus à propos. Va confirmera cela une fois que je reçois le concept de scène ", ou il n'ya plus de référence créée à cet objet, à l'aide de l'affectation de référence ou à toute autre méthode.


BTW, dans votre 2e cas, vous avez oublié une parenthèse là-bas. Il devrait être: xxx


12 commentaires

Il convient de noter généralement que, dans la plupart des cas, un programmeur (en particulier un novice) ne devrait pas s'inquiéter de telles micro-optimisations.


@Adamdyga: Oui, vous avez raison de ne pas vous soucier de micro-optimisations, mais l'OP demande quelle est la différence entre les deux, ce qui est plus rapide et ce qui prend plus de mémoire.


Merci pour votre réponse. Je vous en suis reconnaissant. Comment puis-je uppoter?


@Kensukekonishi. Vous êtes la bienvenue :) Vous pouvez uppouver la réponse en cliquant sur le bouton de votation du côté gauche de la réponse. De plus, si la réponse était utile, vous pouvez le marquer comme accepté, en cliquant sur la flèche sous le bouton de vote.


@Kensukekonishi. Ah! Avez-vous indiqué la réponse par erreur?


Ceci est une erreur. Dans le premier cas, s'il n'y a plus d'utilisations supplémentaires de la variable A , l'objet devient alors admissible à la collecte des ordures immédiatement après l'appel à getvalue . L'éligibilité à la collecte des ordures n'est pas régie par l'existence de variables dans la portée, mais de savoir si l'objet "peut être consulté dans tout calcul permanent potentiel de tout fil en direct". Voir §12.6.1 de La spécification de langue Java .


@Rohitjain j'espère pas. Mais de toute façon j'ai cliqué sur le vote (pour la hausse) maintenant


@Tomanderson. Eh bien, comme la première déclaration indique - un objet accessible est n'importe quel objet qui peut être accessible dans tout calcul continu potentiel de tout thread en direct. , il est clair que nous pouvons toujours accéder à l'objet créé dans le premier cas, plus bas dans la même portée. Peu importe que nous l'utilisions ou non, il est toujours accessible. C'est ce qui le rend inside pour GC.


@Tomanderson. Je prends un objet inaccessible comme celui que nous n'avons aucun moyen d'avoir accès à.


@Rohitjain Si la variable n'est jamais accessible à nouveau, même si nous restons dans la même portée, les JLS spécifient que la collection est autorisée. Le JIT peut même aligner l'appel du constructeur de toute façon. Hotspot en particulier peut effectuer une analyse avancée d'évasion sur des variables telles que celles-ci.


@Tomg. Peut-être que je ne suis pas tout à fait capable de saisir cette section de JLS liée aux commentaires précédents. Peut-être que je vais y jeter un coup d'oeil plus tard. Certainement apprendre une nouvelle chose aujourd'hui, si cela va de cette façon. Merci :)


@Rohitjain: Un calcul continu ne peut faire que quelque chose si elle contient du code pour le faire. Les ordinateurs n'ont pas libre volonté, après tout! Si une méthode ne contient aucun code qui accède à une variable particulière, on ne peut pas y accéder.



1
votes

Pas beaucoup de différence de performance sage.

La principale différence est qu'avec la version en ligne, l'instance créée est disponible pour la collecte des ordures dès que la ligne finie l'exécution et éventuellement avant em> Finition, en fonction de la JVM. p>

Bien que la création d'une instance est assez bon marché, envisagez d'utiliser une méthode statique - créant ainsi l'instance et la collecte de déchets Il peut être évité: P>

public static double getValue(HogeHoge hogehoge) {
    // some impl
}


1 commentaires

Les objets deviennent disponibles pour la collecte des ordures à la même période - voir mon Autre commentaire .



4
votes

Vous pouvez afficher le bytecode pour vous-même: xxx

devient xxx

globalement, il n'y a pas de différence réelle entre ces deux approches dans termes de vitesse, et vous ne devriez pas vous inquiéter des micro-optimisations comme celle-là.


1 commentaires

Merci beaucoup. Maintenant, je me souviendrai que je ne devrais pas me soucier des micro-optimisations.



1
votes

Ma recommandation est de ne pas vous soucier de ces micro-optimisations et de vous concentrer davantage sur la lisibilité de votre code source.

Je choisirais la solution qui facilite la compréhension de ce qui se passe, même si cela nécessite une référence supplémentaire.

En principe, la version sans la variable intermédiaire devrait, bien entendu, enregistrer la mémoire requise par la référence, qui est négligeable, et il devrait mettre à disposition l'objet pour le collecteur des ordures dès que l'opération est exécutée au lieu de la référence. sort de la portée.

Aussi, notez que ce code peut se transformer sur le même code d'octet due à l'optimisation du compilateur, qui est une autre raison pour laquelle vous ne devez pas m'occuper de cela.


1 commentaires

Notez qu'il n'y a pas vraiment de différence dans la collectionnabilité des ordures non plus - voir mon Autre commentaire .



12
votes

En réalité, ce type de code aura une petite différence:

      11: astore_3
      12: aload_3


2 commentaires

+1 Pour mentionner l'optimisation qui ne conduira à aucune différence du tout.


hmm ok im pas familier avec optimisation par jvm ou compilateurs ... mais de toute façon merci beaucoup je comprends



1
votes

FAIT amusant (un peu OT): Sous .NET, un objet peut réellement être soumis à une poubelle avant de sortir de la portée - même si l'une de ses méthodes est toujours exécutée (voir l'exemple de code ci-dessous ou la démonstration en direct à: http://rexter.com/wtksye61526 - imprime "false false" lors de la configuration de la libération et de l'extérieur du débogueur).

Qu'est-ce que cela nous dit?
Eh bien - une version future / une mise en œuvre différente de la JVM pourrait mettre en œuvre un comportement similaire (il est possible qu'il existe même des JVM qui le font déjà).

théoriquement parlant (en supposant un environnement recueilli des ordures), les deux Les options peuvent être considérées comme égales. Ils ne seraient peut-être exécutés qu'un peu différent pendant l'exécution en raison d'un détail de mise en œuvre dans la JVM (s'ils ne sont pas optimisés comme andréemoniy mentionné). Et les détails de la mise en œuvre sont sujets à changement.

Ne vous embêtez pas avec les différences et optez pour plus lisible. xxx


1 commentaires

Je ne sais pas si tout JVM actuel collectera l'objet lorsque la méthode est toujours en cours d'exécution, mais les JVMS sont déjà autorisés à recueillir un objet dès qu'il devient inutilisé, même s'il y a des références encore dans la portée (voir mon Autre commentaire ), et je crois qu'ils le font déjà. Votre prophétie de quelle version future pourrait faire est déjà venue passer!