Quel est le gain de déclarer une méthode comme statique

j'ai récemment regardé mes avertissements dans Eclipse et suis tombé sur celui-ci:

static warning

il donnera un avertissement de compilateur si la méthode peut être déclarée comme statique.

[modifier] citation Exacte au sein de l'Éclipse aider, avec le stress et privé de finale:

une fois activé, le compilateur émettra une erreur ou un avertissement pour méthodes qui sont privées ou finale et qui se réfèrent uniquement à la statique membre.

Oui je sais que je peux l'éteindre, mais je veux savoir la raison de l'allumer?

pourquoi serait-il bon de déclarer que toutes les méthodes possibles sont statiques?

est-ce que cela va donner des avantages de performance? (dans un domaine mobile)

pointant une méthode comme statique, je suppose que montre que vous n'utilisez Aucune variable d'instance donc pourrait être déplacé à une classe de style utils?

à la fin de la journée, est-ce que je devrais simplement éteindre "ignorer" ou dois-je corriger les 100+ Avertissements qu'il m'a donné?

pensez-vous que ce ne sont que des mots-clés supplémentaires que sale le code, comme le compilateur sera juste inlines ces méthodes de toute façon? (un peu comme vous ne déclarez pas chaque variable que vous pouvez finale mais vous pouvez ).

93
demandé sur Maarten Bodewes 2012-06-28 11:44:32

9 réponses

Chaque fois que vous écrivez une méthode, vous remplissez un contrat dans une étendue donnée. Plus la portée est étroite, plus la chance d'écrire un bogue est faible.

Lorsqu'une méthode est statique, vous ne pouvez pas accéder aux membres non statiques; par conséquent, votre portée est plus étroite. Donc, si vous n'avez pas besoin de et n'aurez jamais besoin (même dans les sous-classes) de membres non statiques pour remplir votre contrat, pourquoi donner accès à ces champs à votre méthode? Déclarer la méthode static dans ce cas, permet au compilateur de vérifier que vous n'utilisez pas de membres que vous n'avez pas l'intention d'utiliser.

et de plus, cela aidera les gens qui lisent votre code à comprendre la nature du contrat.

C'est pourquoi il est considéré comme bon de déclarer une méthode static quand il est effectivement la mise en œuvre d'un contrat statique.

dans certains cas, votre méthode signifie seulement quelque chose relatif à une instance de votre class, et il arrive que son implémentation n'utilise pas réellement un champ ou une instance non-statique. Dans de tels cas, vous ne marquerez pas la méthode static .

exemples où vous n'utiliseriez pas le static mot clé:

  • Une extension crochet qui ne fait rien (mais il pourrait faire quelque chose avec les données de l'instance dans une sous-classe)
  • un comportement par défaut très simple destiné à être personnalisable dans une sous-classe.
  • gestionnaire d'Événement de mise en œuvre: mise en œuvre varieront selon la classe du gestionnaire d'événements, mais de ne pas utiliser les biens de l'événement instance de gestionnaire.
129
répondu Samuel Rossille 2016-09-22 22:52:07

Il n'y a pas de concept d'optimisation.

a static méthode est static parce que vous déclarez explicitement que la méthode ne s'appuie sur aucune instance de la classe enveloppante juste parce qu'elle n'en a pas besoin. De sorte que L'avertissement D'éclipse, comme indiqué dans la documentation:

lorsqu'il est activé, le compilateur émet une erreur ou un avertissement pour les méthodes qui sont privées ou finales et qui se réfèrent uniquement aux membres statiques.

si vous n'avez besoin d'Aucune variable d'instance et que votre méthode est privée (ne peut pas être appelée de l'extérieur) ou finale (ne peut pas être modifiée), alors il n'y a aucune raison de la laisser être une méthode normale à la place d'une méthode statique. Une méthode statique est intrinsèquement plus sûre même simplement parce que vous êtes autorisé à faire moins de choses avec elle (il n'a pas besoin d'une instance, vous n'avez pas d'objet implicite this ).

12
répondu Jack 2016-05-12 14:23:42

Je n'ai pas d'information sur la performance, je suppose qu'il est légèrement mieux au plus, puisque le code n'a pas besoin de faire la régulation dynamique basée sur le type.

cependant, un argument beaucoup plus fort contre le remaniement dans les méthodes statiques est que l'utilisation actuelle statique est considérée comme une mauvaise pratique. Les méthodes / variables statiques ne s'intègrent pas bien dans un langage orienté objet et sont également difficiles à tester correctement. C'est la raison pour laquelle certaines langues plus récentes concept de méthodes/variables statiques tout à fait, ou essayer de l'internaliser dans le langage d'une manière qui joue mieux avec OO (par exemple objets en Scala).

la plupart du temps, vous avez besoin de méthodes statiques pour mettre en œuvre des fonctions qui n'utilisent que des paramètres d'entrée et de production d'une sortie en utilisant que (par exemple utilitaire/fonctions d'aide) dans les langues modernes, Il ya un concept de fonction de première classe qui permet que, donc statique n'est pas nécessaire. Java 8 aura des expressions lambda intégré, nous allons donc déjà dans cette direction.

6
répondu Istvan Devai 2012-06-28 08:00:01

1. Declaring method static donne un léger avantage de performance, mais ce qui est plus utile, il permet de l'utiliser sans avoir une instance d'objet à portée de main (pensez par exemple à la méthode de l'usine ou obtenir un singleton). Elle sert également à la documentation, qui sert à expliquer la nature de la méthode. Ce but de documentation ne doit pas être ignoré, car il donne une indication immédiate sur la nature de la méthode aux lecteurs du code et aux utilisateurs de la API et sert également d'outil de réflexion pour le programmeur original - être explicite sur le sens prévu vous aide également à penser correctement et produire un code de meilleure qualité (je pense basé sur mon expérience personnelle, mais les gens sont différents). Par exemple, il est logique et donc souhaitable de faire une distinction entre les méthodes opérant sur un type et les méthodes agissant sur une instance du type (comme le souligne Jon Skeet dans son commentaire à une question C# ).

encore un autre cas d'utilisation pour les méthodes static est d'imiter l'interface de programmation procédurale. Pensez à la classe java.lang.System.println() et aux méthodes et attributs qui s'y trouvent. La classe java.lang.System est utilisée comme un espace de nom de groupe plutôt que comme un objet instanciable.

2. comment Eclipse (ou toute autre entité - biocomposable ou non-biocomposable - programmée ou autre) peut-elle savoir avec certitude quelle méthode pourrait être utilisée? déclarée statique? Même si une classe de base n'accède pas aux variables d'instance ou n'appelle pas des méthodes non statiques, par le mécanisme d'héritage les choses peuvent changer. Ce n'est que si la méthode ne peut pas être supplantée par une sous-classe héritée, que nous pouvons affirmer avec une certitude de 100% que la méthode peut réellement être déclarée static . Remplacement d'une méthode est impossible exactement dans les deux cas de

  1. private (aucune sous-classe ne peut l'utiliser directement et ne Principe savoir), ou
  2. final (même si elle est accessible par la sous-classe, il n'est pas possible de changer la méthode pour faire référence aux données d'instance ou aux fonctions).

D'où la logique de L'option Eclipse.

3. l'affiche originale demande aussi: " pointer une méthode comme statique, je suppose montre que vous n'utilisez Aucune variable d'instance pourrait donc être déplacé à un classe de style utils? " C'est un très bon point. Parfois, ce genre de changement de conception est indiqué par l'avertissement.

c'est une option très utile, que je m'assurerais personnellement d'activer, si J'utilisais Eclipse et si je programmais en Java.

3
répondu FooF 2017-05-23 12:17:43

voir la réponse de Samuel sur la façon dont la portée de la méthode change. Je suppose, c'est l'aspect principal de la prise d'une méthode statique.

vous avez aussi demandé à propos de la performance:

il pourrait y avoir un gain de performance minuscule, parce qu'un appel à une méthode statique ne nécessite pas la référence implicite "ceci" comme paramètre.

cependant, cet impact de performance est vraiment minuscule. Par conséquent, tout est à propos de la portée.

1
répondu Black 2012-06-28 07:56:31

à Partir de l'Android lignes directrices sur le Rendement:

préférez la statique à la Virtuelle si vous n'avez pas besoin d'accéder au champs, faites votre méthode statique. Invocations seront d'environ 15% -20% plus rapide. C'est aussi une bonne pratique, parce que vous pouvez le dire à partir de la méthode signature qui appelle la méthode ne peut pas modifier l'état de l'objet.

http://developer.android.com/training/articles/perf-tips.html#PreferStatic

1
répondu Blundell 2013-07-17 15:12:47

Eh bien, la documentation de L'éclipse dit à propos de l'avertissement en question:

méthode pouvant être statique

"

une fois activé, le compilateur émettra une erreur ou un avertissement pour méthodes qui sont privées ou finales et qui se réfèrent seulement à statique les membres de la

je pense que ça dit presque tout. Si la méthode est privée et finale et se réfère uniquement aux membres statiques, la la méthode en question peut tout aussi bien être déclarée statique et par là, rendre évident que nous n'avons l'intention d'accéder à du contenu statique.

honnêtement, je ne pense pas qu'il y ait une autre raison mystérieuse derrière ça.

0
répondu Edwin Dalorzo 2012-07-03 19:53:52

il manquait des chiffres pour les différences de vitesse. Donc j'ai essayé de les comparer ce qui s'est avéré être pas si facile: Java loop devient plus lent après quelques descentes / la faute de JIT?

j'ai finalement utilisé Caliper et les résultats sont les mêmes que l'exécution de mes tests à la main:

il n'y a pas de différence mesurable pour les appels statiques/dynamiques. du moins pas pour Linux/AMD64/Java7.

Les résultats de Caliper sont ici: https://microbenchmarks.appspot.com/runs/1426eac9-36ca-48f0-980f-0106af064e8f#r:scenario.benchmarkSpec.methodName,scenario.vmSpec.options.CMSLargeCoalSurplusPercent,scenario.vmSpec.options.CMSLargeSplitSurplusPercent,scenario.vmSpec.options.CMSSmallCoalSurplusPercent,scenario.vmSpec.options.CMSSmallSplitSurplusPercent,scenario.vmSpec.options.FLSLargestBlockCoalesceProximity,scenario.vmSpec.options.G1conmarkstepdurationmillis

et mes propres résultats sont:

Static: 352 ms
Dynamic: 353 ms
Static: 348 ms
Dynamic: 349 ms
Static: 349 ms
Dynamic: 348 ms
Static: 349 ms
Dynamic: 344 ms

la classe D'essai Caliper était:

public class TestPerfomanceOfStaticMethodsCaliper extends Benchmark {

    public static void main( String [] args ){

        CaliperMain.main( TestPerfomanceOfStaticMethodsCaliper.class, args );
    }

    public int timeAddDynamic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addDynamic( 1, i );
        }
        return r;
    }

    public int timeAddStatic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addStatic( 1, i );
        }
        return r;
    }

    public int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}

et ma propre classe D'essai était:

public class TestPerformanceOfStaticVsDynamicCalls {

    private static final int RUNS = 1_000_000_000;

    public static void main( String [] args ) throws Exception{

        new TestPerformanceOfStaticVsDynamicCalls().run();
    }

    private void run(){

        int r=0;
        long start, end;

        for( int loop = 0; loop<10; loop++ ){

            // Benchmark

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addStatic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Static: " + ( end - start ) + " ms" );

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addDynamic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Dynamic: " + ( end - start ) + " ms" );

            // Do something with r to keep compiler happy
            System.out.println( r );

        }

    }

    private int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}
0
répondu Scheintod 2014-07-22 16:07:05

Les méthodes que vous pouvez déclarer comme statiques sont celles qui ne nécessitent pas d'instanciation, tels que

public class MyClass
{
    public static string InvertText(string text)
    {
        return text.Invert();
    }
}

que vous pouvez ensuite appeler dans n'importe quelle autre classe sans instancier cette classe.

public class MyClassTwo
{
    public void DoSomething()
    {
        var text = "hello world";
        Console.Write(MyClass.InvertText(text));
    }
}

... Mais c'est quelque chose que vous savez probablement déjà. Il ne vous donne pas de réels avantages en soi, à part le fait qu'il est plus clair que la méthode n'utilise Aucune variable d'instance.

In autrement dit, Vous pouvez tout simplement l'éteindre complètement. Si vous savez que vous n'utiliserez jamais une méthode dans d'autres classes (dans ce cas, elle devrait être privée), vous n'avez pas besoin qu'elle soit statique du tout.

-2
répondu NeroS 2012-07-08 08:40:43