Java: quand utiliser des méthodes statiques

911

Je me demande quand utiliser des méthodes statiques? Disons que si j'ai une classe avec quelques getters et setters, une ou deux méthodes, et que je veux que ces méthodes soient invocables uniquement sur un objet instance de la classe. Est-ce à dire que je devrais utiliser une méthode statique?

par exemple

Obj x = new Obj();
x.someMethod

ou

Obj.someMethod

(est-ce la manière statique?)

Je suis plutôt confus!

KP65
la source

Réponses:

1458

Une règle d'or: demandez-vous "Est-il judicieux d'appeler cette méthode, même si aucun objet n'a encore été construit?" Si tel est le cas, il devrait certainement être statique.

Donc, dans une classe, Carvous pourriez avoir une méthode:

double convertMpgToKpl(double mpg)

... qui serait statique, car on pourrait vouloir savoir à quoi convertit 35mpg, même si personne n'a jamais construit de fichier Car. Mais cette méthode (qui définit l'efficacité d'un particulier Car):

void setMileage(double mpg)

... ne peut pas être statique car il est inconcevable d'appeler la méthode avant d'en Caravoir construit une.

(Soit dit en passant, l'inverse n'est pas toujours vrai: vous pouvez parfois avoir une méthode qui implique deux Carobjets, et toujours vouloir qu'elle soit statique. Par exemple:

Car theMoreEfficientOf( Car c1, Car c2 )

Bien que cela puisse être converti en une version non statique, certains diront que puisqu'il n'y a pas de choix "privilégié" qui Carest plus important, vous ne devriez pas forcer un appelant à en choisir un Carcomme objet que vous invoquerez le méthode activée. Cette situation représente cependant une fraction assez faible de toutes les méthodes statiques.)

pas-juste-yeti
la source
325
Quelques bons exemples ici. J'ajouterais cependant que «statique» est souvent utile lorsque vous savez que quelque chose ne changera pas entre les instances. Si tel est le cas, je considérerais vraiment le "principe de responsabilité unique", qui implique qu'une classe devrait avoir une responsabilité et donc une seule raison de changer. Je pense que l'on devrait envisager de déplacer la fonction "ConvertMpgToKpl (double mpg)", et des méthodes similaires, dans leur propre classe. Le but d'un objet voiture est de permettre l'instanciation des voitures, et non de fournir une comparaison entre elles. Ceux-ci devraient être externes à la classe.
Zack Jannsen
34
Je pense que je préférerais la méthode Car#isMoreEfficientThan(Car). Il a l'avantage que la voiture que vous retournez en égalité n'est pas arbitraire. Il est évident par le titre de la méthode ce qui est retourné en cas d'égalité.
Cruncher
5
Je serais également prudent lors de la création d'une méthode statique qui utilise des ressources externes (système de fichiers, base de données, etc.) ce type de statique peut rendre horrible de tester les méthodes consommatrices. J'essaie personnellement de garder la statique dans le domaine de "l'utilité".
Seth M.
7
En fait, il devrait être implémenté en tant que comparateur .
Dogweather
3
@ B1KMusic Bien sûr. Ce que je veux dire par "quelle voiture est retournée en égalité", c'est "de vraies cartes vers la voiture appelée et de fausses cartes vers la voiture dépassée". C'est sans ambiguïté.
Cruncher
538

Définissez les méthodes statiques uniquement dans les scénarios suivants:

  1. Si vous écrivez des classes utilitaires et qu'elles ne sont pas censées être modifiées.
  2. Si la méthode n'utilise aucune variable d'instance.
  3. Si une opération ne dépend pas de la création d'instance.
  4. S'il existe du code qui peut être facilement partagé par toutes les méthodes d'instance, extrayez ce code dans une méthode statique.
  5. Si vous êtes sûr que la définition de la méthode ne sera jamais modifiée ou remplacée. Comme les méthodes statiques ne peuvent pas être remplacées.
Mohd
la source
46
de bons points, mais ce sont des exigences si vous voulez rendre une méthode statique, pas des raisons pour en faire une.
tetsuo
4
@Mohd sur l'exigence 5: quand pouvez-vous être sûr à 100% qu'une méthode ne sera jamais modifiée ou remplacée? N'y a-t-il pas toujours des facteurs inconnus que vous ne pouvez pas prendre en compte au moment d'écrire votre méthode statique?
PixelPlex
8
Les "classes utilitaires" sont très difficiles à raisonner, la mauvaise chose est que tôt ou tard tout commence à "ressembler" à un utilitaire (ouais je fais référence à ce paquet "util" qui est gonflé, intouchable et mal testé), et vos cas de test auront besoin de plus de travail (se moquer des utilitaires statiques est DUR). Préférez d'abord les objets.
Sergio
2
@Mohd cette réponse est exactement ce que je recherche. J'ai rencontré beaucoup de problèmes en utilisant des méthodes statiques en multithreading. Pouvez-vous s'il vous plaît élaborer les points 2, 3 de plus (avec l'exemple 100 pouces pour vous)
Prakash Pandey
Je pense qu'une "classe statique" devrait être inventée si vous allez utiliser des variables et des méthodes statiques.
Robert Rocha
182

Il existe des raisons valables d'utiliser des méthodes statiques:

  • Performances : si vous voulez que du code soit exécuté et que vous ne voulez pas instancier un objet supplémentaire pour le faire, insérez-le dans une méthode statique. La JVM peut également optimiser beaucoup les méthodes statiques (je pense avoir lu James Gosling une fois déclarant que vous n'avez pas besoin d'instructions personnalisées dans la JVM, car les méthodes statiques seront tout aussi rapides, mais ne trouveront pas la source - donc cela pourrait être complètement faux). Oui, c'est de la micro-optimisation, et probablement inutile. Et nous, les programmeurs, ne faisons jamais de choses inutiles simplement parce qu'elles sont cool, non?

  • Pratique : au lieu d'appeler new Util().method(arg), d'appeler Util.method(arg)ou method(arg)avec des importations statiques. Plus facile, plus court.

  • Ajout de méthodes : vous vouliez vraiment que la classe String ait une removeSpecialChars()méthode d'instance, mais elle n'est pas là (et elle ne devrait pas, car les caractères spéciaux de votre projet peuvent être différents des autres projets), et vous ne pouvez pas l'ajouter (depuis Java est un peu sain d'esprit), vous créez donc une classe utilitaire et appelez à la removeSpecialChars(s)place de s.removeSpecialChars(). Doux.

  • Pureté : en prenant quelques précautions, votre méthode statique sera une fonction pure , c'est-à-dire que la seule chose dont elle dépend est ses paramètres. Données entrantes, données sortantes. C'est plus facile à lire et à déboguer, car vous n'avez pas à vous soucier des bizarreries d'héritage. Vous pouvez aussi le faire avec les méthodes d'instance, mais le compilateur vous aidera un peu plus avec les méthodes statiques (en n'autorisant pas les références aux attributs d'instance, en remplaçant les méthodes, etc.).

Vous devrez également créer une méthode statique si vous voulez faire un singleton, mais ... ne le faites pas. Je veux dire, réfléchissez-y à deux fois.

Maintenant, plus important encore, pourquoi ne voudriez-vous pas créer une méthode statique? Fondamentalement, le polymorphisme sort par la fenêtre . Vous ne pourrez pas remplacer la méthode, ni la déclarer dans une interface (pré-Java 8) . Cela prend beaucoup de flexibilité de votre conception. De plus, si vous avez besoin d'un état , vous vous retrouverez avec de nombreux bugs et / ou goulots d'étranglement en cas de non-prudence.

tetsuo
la source
1
Un grand nombre de bonnes raisons énumérées ici lorsque la statique peut être utile. Une autre chose à laquelle je peux penser est que l'écriture de tests unitaires pour de telles méthodes est tout simplement simple
nilesh
@tetsuo Merci! Votre explication est très claire et les raisons fournies sont très logiques et ont beaucoup de sens.
Deniss M.
3
Et nous, les programmeurs, ne faisons jamais de choses inutiles simplement parce qu'elles sont cool, non? +1
Scaramouche
Cela dit, une méthode statique devient une fonction nommée complète stackoverflow.com/questions/155609/…
Ivanzinho
Je suis d'accord avec la performance et l'aspect pratique, mais pas avec la pureté. La méthode statique peut modifier les membres statiques de la classe (qui peuvent être privés). Cela peut être utile. Par exemple, vous pourriez avoir une méthode comme "static synchronized int allocateID () {return idNext ++;}". En fait, une méthode statique peut être tout aussi pure ou impure qu'une méthode non statique en termes d'effets secondaires.
Adam Gawne-Cain
42

Après avoir lu les articles de Misko, je pense que les méthodes statiques sont mauvaises du point de vue des tests. Vous devriez avoir des usines à la place (peut-être en utilisant un outil d'injection de dépendances comme Guice ).

comment puis-je m'assurer que je n'ai qu'une chose

seulement avoir un de quelque chose Le problème de "comment puis-je m'assurer que je n'ai qu'un seul de quelque chose" est bien contourné. Vous instanciez uniquement une seule ApplicationFactory dans votre main et, par conséquent, vous instanciez uniquement une seule instance de tous vos singletons.

Le problème de base avec les méthodes statiques est qu'elles sont du code procédural

Le problème de base avec les méthodes statiques est qu'elles sont du code procédural. Je ne sais pas comment tester le code procédural unitaire. Les tests unitaires supposent que je peux instancier une partie de mon application de manière isolée. Pendant l'instanciation, je câble les dépendances avec des simulacres / amicaux qui remplacent les vraies dépendances. Avec la programmation procédurale, il n'y a rien à "câbler" car il n'y a pas d'objets, le code et les données sont séparés.

Alfred
la source
20
Je ne comprends pas la partie de ne pas pouvoir tester le code de procédure unitaire. Ne vous contentez-vous pas de configurer des cas de test qui mappent une entrée correcte à une sortie correcte en utilisant la méthode statique avec la classe comme «unité»?
tjb
2
Vous pouvez le faire pour tester ces fonctions. Mais lorsque vous utilisez ces méthodes statiques dans d'autres classes que vous souhaitez tester, je pense que vous ne pouvez pas les simuler (faux / amicaux) ou quoi que ce soit, car vous ne pouvez pas instancier une classe.
Alfred
4
@Alfred: Jetez un œil à PowerMock qui a la capacité de se moquer des méthodes statiques. En utilisant PowerMock, il existe peu de scénarios, le cas échéant, où vous trouverez des dépendances de méthode qui ne peuvent pas être moquées.
Carles Sala
7
Vous pouvez tester les statistiques unitaires à l'aide de PowerMock, mais vous constaterez bientôt que vous manquez d'espace Permgen (fait, vous avez obtenu le T-shirt), et c'est toujours méchant. Sauf si vous SAVEZ (basé sur au moins une décennie de votre propre expérience dans de véritables langues OO, ne migrant pas de C), alors NE LE FAITES PAS. Sérieusement, le pire code que j'ai jamais vu provenait de l'utilisation de la statique par un développeur intégré et dans la plupart des cas, nous étions coincés avec cela, pour toujours, et l'ajout de plus de code nous enfermait encore plus étroitement dans le monolithe non modifiable. Couplage lâche: non, testable: à peine, modifiable: JAMAIS. Éviter!
user1016765
14
Je peux comprendre la difficulté de tester des méthodes statiques qui dépendent de l'état statique. Mais lorsque vous testez des méthodes statiques sans état comme Math.abs()ou Arrays.sort(), même des méthodes dans lesquelles vous pouvez passer toutes les dépendances , je ne vois pas comment cela pourrait empêcher le test unitaire. Je dirais qu'une règle empirique simple est la suivante: si vous avez une raison de vous moquer de la logique procédurale, ne la mettez pas dans une méthode statique. Je n'ai jamais eu de raison de me moquer Arrays.sort()ou Math.abs().
Andy
36

Une staticméthode est un type de méthode qui n'a besoin d'aucun objet à initialiser pour être appelée. Avez-vous remarqué qu'il staticest utilisé dans la mainfonction Java? L'exécution du programme commence à partir de là sans qu'un objet soit créé.

Prenons l'exemple suivant:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }
Zishan
la source
meilleure réponse en fait
Yahya
20

Les méthodes statiques en java appartiennent à la classe (et non à une instance de celle-ci). Ils n'utilisent aucune variable d'instance et prennent généralement les données des paramètres, effectuent des actions dessus, puis renvoient un résultat. Les méthodes d'instances sont associées aux objets et, comme leur nom l'indique, peuvent utiliser des variables d'instance.

Kevin Sylvestre
la source
12

Non, les méthodes statiques ne sont pas associées à une instance; ils appartiennent à la classe. Les méthodes statiques sont votre deuxième exemple; les méthodes d'instance sont les premières.

duffymo
la source
1
Vous devez utiliser des méthodes statiques si vous n'avez pas besoin des manipulations d'état de l'objet.
MastAvalons
11

Si vous appliquez un mot clé statique avec n'importe quelle méthode, il est appelé méthode statique.

  1. Une méthode statique appartient à la classe plutôt qu'à l'objet d'une classe.
  2. Une méthode statique invoquée sans avoir besoin de créer une instance d'une classe.
  3. La méthode statique peut accéder aux membres de données statiques et peut en modifier la valeur.
  4. Une méthode statique est accessible en utilisant simplement le nom d'un nom statique de point de classe. . . exemple: Student9.change ();
  5. Si vous souhaitez utiliser des champs non statiques d'une classe, vous devez utiliser une méthode non statique.

// Programme de modification de la propriété commune de tous les objets (champ statique).

class Student9{  
 int rollno;  
 String name;  
 static String college = "ITS";  

 static void change(){  
 college = "BBDIT";  
 }  

 Student9(int r, String n){  
 rollno = r;  
 name = n;  
 }  

 void display (){System.out.println(rollno+" "+name+" "+college);}  

public static void main(String args[]){  
Student9.change();  

Student9 s1 = new Student9 (111,"Indian");  
Student9 s2 = new Student9 (222,"American");  
Student9 s3 = new Student9 (333,"China");  

s1.display();  
s2.display();  
s3.display();  
}  }

O / P: 111 Indien BBDIT 222 Américain BBDIT 333 Chine BBDIT

IndianProgrammer1234
la source
10

Les méthodes statiques ne sont pas associées à une instance, elles ne peuvent donc pas accéder aux champs non statiques de la classe.

Vous utiliseriez une méthode statique si la méthode n'utilise aucun champ (ou seulement des champs statiques) d'une classe.

Si des champs non statiques d'une classe sont utilisés, vous devez utiliser une méthode non statique.

Carsten
la source
1
Réponse claire, courte et simple.
Josi
8

Les méthodes statiques doivent être appelées sur la classe, les méthodes d'instance doivent être appelées sur les instances de la classe. Mais qu'est-ce que cela signifie en réalité? Voici un exemple utile:

Une classe de voiture peut avoir une méthode d'instance appelée Accelerate (). Vous ne pouvez accélérer une voiture que si la voiture existe réellement (a été construite) et que ce serait donc une méthode d'instance.

Une classe de voiture peut également avoir une méthode de comptage appelée GetCarCount (). Cela retournerait le nombre total de voitures créées (ou construites). Si aucune voiture n'a été construite, cette méthode retournerait 0, mais elle devrait toujours pouvoir être appelée, et donc il faudrait que ce soit une méthode statique.

Charlie Seligman
la source
6

En fait, nous utilisons des propriétés et des méthodes statiques dans une classe, lorsque nous voulons utiliser une partie de notre programme devrait exister jusqu'à ce que notre programme soit en cours d'exécution. Et nous savons que, pour manipuler les propriétés statiques, nous avons besoin de méthodes statiques car elles ne font pas partie de la variable d'instance. Et sans méthodes statiques, la manipulation des propriétés statiques prend du temps.

Sagar
la source
Garder l'état dans des variables statiques est une mauvaise chose à faire pour de nombreuses raisons - comme la sécurité multi-threading, le débogage, l'encapsulation des données ... etc, etc. Un bon exemple serait une classe d'utilité, par exemple des calculs mathématiques.
Vladimir Demirev
5

Utilisez une méthode statique lorsque vous souhaitez pouvoir accéder à la méthode sans instance de la classe.

Jamey
la source
29
Cela ne donne aucune justification à la conception d'un programme.
adamjmarkham
4

Statique: Obj.someMethod

À utiliser staticlorsque vous souhaitez fournir un accès de niveau classe à une méthode, c'est-à-dire où la méthode doit être appelable sans instance de la classe.

Finbarr
la source
4

Les méthodes statiques n'ont pas besoin d'être invoquées sur l'objet et c'est à ce moment que vous l'utilisez. Exemple: votre Main () est un objet statique et vous ne créez pas d'objet pour l'appeler.

Vaishak Suresh
la source
1
Yay! Regardez où je suis venu en recherchant des questions sur Java noobie! C'est un petit monde :-)
Deepak
1
@Deepak small world Indeed :)
Vaishak Suresh
4

Les méthodes et variables statiques sont une version contrôlée des fonctions et variables «globales» en Java. Dans quelles méthodes sont accessibles en tant que classname.methodName()ou classInstanceName.methodName(), c'est-à-dire que les méthodes et variables statiques sont accessibles en utilisant le nom de classe ainsi que les instances de la classe.

La classe ne peut pas être déclarée comme statique (car cela n'a aucun sens. Si une classe est déclarée publique, elle est accessible de n'importe où), les classes internes peuvent être déclarées statiques.

Manju Yadav
la source
3

Des méthodes statiques peuvent être utilisées si

  • On ne veut pas effectuer une action sur une instance (méthodes utilitaires)

    Comme mentionné dans quelques-unes des réponses ci-dessus dans ce post, convertir des miles en kilomètres ou calculer la température de Fahrenheit en Celsius et vice-versa. Avec ces exemples utilisant une méthode statique, il n'a pas besoin d'instancier un nouvel objet entier dans la mémoire de tas. Considérez ci-dessous

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 
    2. ABCClass.convertFarenheitToCelcium(double farenheit)

    le premier crée une nouvelle empreinte de classe pour chaque méthode invoquée, Performance, Practical . Les exemples sont la classe StringUtils de la bibliothèque Math et Apache-Commons ci-dessous:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
  • On veut utiliser comme une fonction simple. Les entrées sont explicitement transmises et obtiennent les données de résultat comme valeur de retour. L'hérédité, l'instanciation d'objet n'entre pas en scène. Concis, lisible .

REMARQUE : Peu de gens s'opposent à la testabilité des méthodes statiques, mais les méthodes statiques peuvent également être testées! Avec jMockit, on peut se moquer des méthodes statiques. Testabilité . Exemple ci-dessous:

new MockUp<ClassName>() {
    @Mock
    public int doSomething(Input input1, Input input2){
        return returnValue;
    }
};
Amit Kaneria
la source
3

Les méthodes statiques sont les méthodes en Java qui peuvent être appelées sans créer un objet de classe. Il appartient à la classe.

Nous utilisons une méthode statique lorsque nous n'avons pas besoin d'être invoquée en utilisant une instance.

rashedcs
la source
2

Je me demande quand utiliser des méthodes statiques?

  1. Une utilisation courante des staticméthodes consiste à accéder aux staticchamps.
  2. Mais vous pouvez avoir des staticméthodes, sans référencer de staticvariables. Des méthodes d'assistance sans staticvariable de référence peuvent être trouvées dans certaines classes java comme java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. L'autre cas d'utilisation, je peux penser à ces méthodes combinées avec la synchronizedméthode est l'implémentation du verrouillage au niveau de la classe dans un environnement multi-thread.

Disons que si j'ai une classe avec quelques getters et setters, une ou deux méthodes, et que je veux que ces méthodes soient invocables uniquement sur un objet instance de la classe. Est-ce à dire que je devrais utiliser une méthode statique?

Si vous devez accéder à la méthode sur un objet instance de la classe, votre méthode doit être non statique.

La page de documentation Oracle fournit plus de détails.

Toutes les combinaisons de variables et méthodes d'instance et de classe ne sont pas autorisées:

  1. Les méthodes d'instance peuvent accéder directement aux variables d'instance et aux méthodes d'instance.
  2. Les méthodes d'instance peuvent accéder directement aux variables de classe et aux méthodes de classe.
  3. Les méthodes de classe peuvent accéder directement aux variables de classe et aux méthodes de classe.
  4. Les méthodes de classe ne peuvent pas accéder directement aux variables d'instance ou aux méthodes d'instance: elles doivent utiliser une référence d'objet. De plus, les méthodes de classe ne peuvent pas utiliser le mot clé this car il n'y a pas d'instance à laquelle faire référence.
Ravindra babu
la source
Ne pouvons-nous pas accéder aux champs statiques par des méthodes régulières? Alors ce A common use for static methods is to access static fields.n'est pas un argument.
parsecer
2

Une méthode statique a deux objectifs principaux:

  1. Pour les méthodes utilitaires ou d'assistance qui ne nécessitent aucun état d'objet. Puisqu'il n'est pas nécessaire d'accéder aux variables d'instance, le fait d'avoir des méthodes statiques élimine le besoin pour l'appelant d'instancier l'objet juste pour appeler la méthode.
  2. Pour l'état partagé par toutes les instances de la classe, comme un compteur. Toutes les instances doivent partager le même état. Les méthodes qui utilisent simplement cet état doivent également être statiques.
hemanto
la source
1

Dans eclipse, vous pouvez activer un avertissement qui vous aide à détecter les méthodes statiques potentielles. (Au-dessus de la ligne en surbrillance, j'en ai oublié une autre)

réglage de l'éclipse

ave4496
la source
0

Chaque fois que vous ne souhaitez pas créer un objet pour appeler une méthode dans votre code, déclarez simplement cette méthode comme statique. Étant donné que la méthode statique n'a pas besoin d'une instance pour être appelée avec mais le catch ici n'est pas toutes les méthodes statiques sont appelées par JVM automatiquement. Ce privilège n'est utilisé que par la méthode main () "public static void main [String ... args]" en java car au Runtime, c'est la méthode Signature public "static" void main [] recherchée par la JVM comme point d'entrée pour démarrer l'exécution du code.

Exemple:

public class Demo
{
   public static void main(String... args) 
   {
      Demo d = new Demo();

      System.out.println("This static method is executed by JVM");

     //Now to call the static method Displ() you can use the below methods:
           Displ(); //By method name itself    
      Demo.Displ(); //By using class name//Recommended
         d.Displ(); //By using instance //Not recommended
   }

   public static void Displ()
   {
      System.out.println("This static method needs to be called explicitly");
   }
} 

Sortie: - Cette méthode statique est exécutée par JVM Cette méthode statique doit être appelée explicitement Cette méthode statique doit être appelée explicitement Cette méthode statique doit être appelée explicitement

Amrit
la source