Disons que j'ai une classe conçue pour être instanciée. J'ai plusieurs méthodes "d'assistance" privées à l'intérieur de la classe qui ne nécessitent aucun accès à aucun des membres de la classe et fonctionnent uniquement sur leurs arguments, renvoyant un résultat.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Y a-t-il une raison particulière de spécifier computeOne
et en computeMore
tant que méthodes statiques - ou une raison particulière de ne pas le faire?
Il est certainement plus facile de les laisser comme non statiques, même s'ils peuvent certainement être statiques sans causer de problèmes.
java
static
methods
static-methods
avalys
la source
la source
Réponses:
Je préfère que ces méthodes d'aide soient
private static
; ce qui indiquera clairement au lecteur qu'il ne modifiera pas l'état de l'objet. Mon IDE montrera également les appels aux méthodes statiques en italique, donc je saurai que la méthode est statique sans regarder la signature.la source
protected static
ce qui les rend testables très facilement dans une classe de test dans le même package.static
(si nous voulons juste le tester).Cela pourrait entraîner un bytecode légèrement plus petit, car les méthodes statiques n'auront pas accès à
this
. Je ne pense pas que cela fasse une différence de vitesse (et si c'était le cas, ce serait probablement trop petit pour faire une différence dans l'ensemble).Je les rendrais statiques, car je le fais généralement si possible. Mais c'est juste moi.
EDIT: Cette réponse ne cesse de faire l'objet d'un vote négatif, peut-être en raison de l'assertion non étayée de la taille du bytecode. Je vais donc réellement effectuer un test.
Bytecode (récupéré avec
javap -c -private TestBytecodeSize
):L'appel de la méthode statique prend deux octets (octets?):
iconst_0
(Pour l'argument) etinvokestatic
.L'invocation de la méthode non statique en prend trois:
aload_1
(pour l'TestBytecodeSize
objet, je suppose),iconst_0
(pour l'argument), etinvokespecial
. (Notez que si ceux - ci n'avaient pas des méthodes privées, il aurait été auinvokevirtual
lieu deinvokespecial
, voir JLS Méthodes §7.7 Invocation .)Maintenant, comme je l'ai dit, je ne m'attends pas à ce qu'il y ait une grande différence de performances entre ces deux, à part le fait que cela
invokestatic
nécessite un bytecode de moins.invokestatic
etinvokespecial
devraient tous deux être légèrement plus rapides queinvokevirtual
, car ils utilisent tous deux une liaison statique au lieu de dynamique, mais je n'ai aucune idée si l'un est plus rapide que l'autre. Je ne trouve pas non plus de bonnes références. Le plus proche que je peux trouver est cet article de JavaWorld de 1997 , qui reprend essentiellement ce que je viens de dire:Mais beaucoup de choses ont changé depuis 1997.
Donc en conclusion ... Je suppose que je reste fidèle à ce que j'ai dit auparavant. La vitesse ne devrait pas être la raison de choisir l'un plutôt que l'autre, car ce serait au mieux une micro-optimisation.
la source
Ma préférence personnelle serait de les déclarer statiques, car c'est un indicateur clair qu'ils sont apatrides.
la source
La réponse est ... cela dépend.
Si le membre est une variable d'instance spécifique à l'objet que vous traitez, alors pourquoi la passer comme paramètre?
Par exemple:
la source
L'une des raisons pour lesquelles vous pouvez déclarer des méthodes d'assistance statiques est si vous devez les appeler dans le constructeur de classe "avant"
this
ousuper
. Par exemple:Ceci est un peu un exemple artificiel mais ne
recoverInt
peut clairement pas être une méthode d'instance dans ce cas.la source
Je ne peux pas vraiment penser à des avantages clairs pour la méthode statique privée. Cela étant dit, il n'y a pas non plus d'avantages spécifiques à les rendre non statiques. C'est principalement une question de présentation: vous voudrez peut-être les rendre statiques pour souligner clairement qu'ils ne modifient pas un objet.
Pour une méthode avec différents privilèges d'accès, je pense qu'il y a deux arguments principaux:
En plus de cela, la différence est assez petite, et je doute fortement que le supplément de ce pointeur passé à la méthode d'instance fasse une différence significative.
la source
La bonne réponse est:
toute méthode qui ne prend aucune information d'un champ et ne met aucune information dans un champ ne doit pas être une méthode d'instance. Toute méthode qui n'utilise ni ne modifie aucun champ de sa classe ou de son objet peut également être une méthode statique.
la source
Oui.
En les conservant comme méthodes d'instance, vous vous autorisez à fournir une implémentation différente ultérieurement.
Cela peut sembler idiot (et ce serait le cas si ces méthodes ne sont utilisées que par vous dans un programme de 50 lignes) mais dans des applications plus grandes ou dans des bibliothèques utilisées par quelqu'un d'autre, vous pouvez décider de choisir une meilleure implémentation, mais ne le faites pas veulent casser le code existant.
Vous créez donc une sous-classe et renvoyez cela dans les nouvelles versions, et puisque les méthodes ont été déclarées comme méthodes d'instance, vous laissez simplement le polymorphisme faire son travail.
En outre, vous pouvez bénéficier de la confidentialité du constructeur et fournir une méthode d'usine statique pour la même raison.
Donc, ma recommandation est de les conserver en tant que méthodes d'instance, et d'éviter le statique si possible.
Profitez du dynamisme du langage.
Voir ici pour une vidéo quelque peu connexe: Comment concevoir une bonne API et pourquoi elle est importante
Bien qu'il ne soit pas directement lié à la discussion sur la méthode "statique vs instance", il touche à certains points intéressants de la conception de l'API.
la source
Un problème lié aux méthodes statiques est qu'elles peuvent rendre l'objet plus difficile à utiliser dans les tests unitaires . Mockito ne peut pas créer de maquette pour les méthodes statiques et vous ne pouvez pas créer une implémentation de sous-classe de la méthode.
la source
Si la méthode est fondamentalement juste un sous-programme qui n'utilisera jamais de manière prévisible les informations d'état, déclarez-la statique.
Cela lui permet d'être utilisé dans d'autres méthodes statiques ou dans l'initialisation de classe, c'est-à-dire:
la source
La question statique / non statique se résume à "aurai-je vraiment besoin d'utiliser un objet de cette classe"?
Alors, passez-vous l'objet entre différentes méthodes? L'objet contient-il des informations utiles en dehors du contexte des méthodes statiques? Y a-t-il une raison de ne pas définir les méthodes dans les deux sens si vous les utilisez dans les deux sens?
Si vous êtes dans ce dilemme, il me semble que vous disposez de toutes les données requises pour la méthode flottant dans votre code en dehors de l'objet. c'est ce que tu veux? Serait-il plus facile de simplement toujours collecter ces données dans un objet à chaque fois? Vous pourriez simplement être ambivalent quant à la validation d'un modèle unique. Si vous pouvez tout faire dans un sens, choisissez soit statique ou non statique et allez-y.
la source
Ma préférence dans des cas comme ceux - ci est de faire
computeOne
et lescomputeMore
méthodes statiques. La raison: l'encapsulation. Moins il y a de code qui a accès à l'implémentation de votre classe, mieux c'est.Dans l'exemple que vous donnez, vous déclarez cela
computeOne
etcomputeMore
vous ne devriez pas avoir besoin d'accéder aux internes de la classe, alors pourquoi donner aux responsables de la classe la possibilité de se mêler des internes.la source
Je voudrais clarifier peu de choses que d'autres affiches ont dites comme donnant de fausses informations.
Premièrement, puisque les méthodes sont privées même si vous les déclarez statiques, vous ne pourrez pas y accéder en dehors de cette classe. Deuxièmement, ils sont privés, vous ne pouvez donc même pas remplacer la sous-classe, donc statique ou non statique ne fait aucune différence. Troisièmement, une méthode privée non statique peut également être appelée à partir d'un constructeur de la classe, elle n'a pas besoin d'être statique.
Venons-en maintenant à votre question de savoir si une méthode d'assistance privée doit être définie comme statique ou non statique. Je vais aller avec la réponse de Steve car le marquage d'une méthode privée statique montre que cette méthode est sans état car je respecte également cette règle lorsque je code.
la source
D'après l'expérience, je dirais que ces méthodes privées ont tendance à être assez universelles et réutilisables.
Je pense que la première chose à faire est de se demander si la méthode peut être utile en dehors du contexte de classe actuel. Si c'est le cas, je ferais exactement ce que tout le monde suggère et extrairais cette méthode comme statique pour certaines classes d'utilitaires où quelqu'un devrait, espérons-le, vérifier avant d'implémenter une nouvelle méthode faisant exactement la même chose.
De telles méthodes privées à usage général sont à l'origine d'une grande partie de la duplication de code dans le projet car chaque développeur les réinvente indépendamment juste à l'endroit où il doit l'utiliser. La centralisation de ces méthodes est donc une voie à suivre.
la source
Plus précisément à l'exemple que vous avez donné, il semble que le but de la définition de ces méthodes soit plus pour la clarté du code lorsque vous le lisez que pour la fonctionnalité (elles sont définies comme privées). Dans ce cas, aller avec statique ne fait vraiment rien pour vous, car le but de statique est d'exposer les fonctionnalités de classe.
la source
L'une des raisons est que, toutes choses étant égales par ailleurs, les appels de méthode statique devraient être plus rapides. Les méthodes statiques ne peuvent pas être virtuelles et ne prennent pas implicitement cette référence.
la source
Comme beaucoup de gens l'ont dit, faites-le comme un statique ! Voici la règle générale que je suis: si vous pensez que la méthode est juste une fonction mathématique, c'est-à-dire qu'elle est sans état, n'implique aucune variable d'instance (=> pas de variable de couleur bleue [dans l'éclipse] dans la méthode), et le résultat de la méthode sera la même pour le nombre «n» d'appels (avec les mêmes paramètres, bien sûr), puis marquez cette méthode comme STATIQUE.
Et si vous pensez que cette méthode sera utile à une autre classe, déplacez-la dans une classe Util dans le cas contraire, mettez la méthode en privé dans la même classe. (minimiser l'accessibilité)
la source
Hors sujet: je conserverais les méthodes d'assistance dans une classe utilitaire / assistant autonome avec uniquement des méthodes statiques.
Le problème avec les méthodes d'aide au point d'utilisation (lire «même classe») est qu'une personne en bas de la ligne peut simplement choisir de publier ses propres méthodes d'aide non liées au même endroit
la source
L'avantage des méthodes statiques privées est qu'elles peuvent être réutilisées ultérieurement si vous devez réinitialiser la variable de classe.
la source
Sans le modificateur statique, vous ne pouvez pas comprendre que la méthode est sans état sans analyse supplémentaire qui peut être facilement effectuée lorsque vous (ré) écrivez la méthode.
Ensuite, le modificateur "statique" peut vous donner des idées sur la refactorisation en plus d'autres choses que d'autres peuvent trouver inutiles. Par exemple, déplacer la méthode vers une classe Utility ou la convertir en méthode membre.
la source
Je les déclarerais comme statiques pour les signaler comme apatrides.
Java n'a pas de meilleur mécanisme pour les opérations mineures qui ne sont pas exportées, donc je pense que la statique privée est acceptable.
la source