65 votes

Devrait Java les méthodes statiques par défaut?

Dire que vous êtes de la méthode d'écriture foo() dans la classe A. foo n'a pas toujours accès à tout Un état. Vous ne savez rien d'autre à propos de ce que toto n', ou comment il se comporte. Il pourrait faire n'importe quoi.

Devrait foo toujours être statique, indépendamment de toute autre considération? Pourquoi pas?

Il semble que mes cours sont toujours accumuler de nombreuses méthodes d'assistance, comme je l'ai diviser les tâches et d'appliquer la seule écriture-il-une fois le principe. La plupart de ces ne comptez pas sur l'état de l'objet, mais ne serait jamais utile à l'extérieur de la classe de ses propres méthodes. Devraient-ils être statique par défaut? Est-ce mal de se retrouver avec un grand nombre d'internes des méthodes statiques?

50voto

Bruno Reis Points 16132

Pour répondre à la question sur le titre, en général, les méthodes de Java doit pas être statique par défaut. Java est un langage orienté-objet.

Cependant, ce que vous dites est un peu différent. Vous parler plus précisément des méthodes d'assistance.

Dans le cas de méthodes d'aide qui vient de prendre les valeurs que les paramètres et retourner une valeur, sans accéder à l'état, ils doivent être statique. Privé et statique. Permettez-moi de le souligner:

Les méthodes d'aide qui ne sont pas en état d'accès doit être statique.


1. Avantage majeur: le code est plus expressif.

Faire de ces méthodes statiques a au moins un avantage majeur: vous rendre totalement explicite dans le code de la méthode n'a pas besoin de connaître l'état de l'instance.

Le code parle de lui-même. Les choses deviennent plus évidents pour d'autres personnes qui vont lire votre code, et de même pour vous à un certain point dans l'avenir.

2. Un autre avantage: le code peut être plus simple de raisonner sur.

Si vous assurez-vous que la méthode ne dépend pas de l'externe ou de l'état global, alors que c'est une fonction pure, c'est à dire, une fonction au sens mathématique: pour la même entrée, vous pouvez être certain d'obtenir toujours le même résultat.

3. L'optimisation des avantages

Si la méthode est statique et est une fonction pure, dans certains cas, il pourrait être memoized pour obtenir des gains de performance (dans le changement de l'utilisation de plus de mémoire).

4. Bytecode-les différences de niveau de

Au niveau du bytecode, si vous déclarez l'aide de la méthode comme une méthode d'instance ou comme une méthode statique, vous obtiendrez deux choses complètement différentes.

Pour aider à rendre cette section plus facile à comprendre, prenons un exemple:

public class App {
    public static void main(String[] args) {
        WithoutStaticMethods without = new WithoutStaticMethods();
        without.setValue(1);
        without.calculate();

        WithStaticMethods with = new WithStaticMethods();
        with.setValue(1);
        with.calculate();
    }
}

class WithoutStaticMethods {

    private int value;

    private int helper(int a, int b) {
        return a * b + 1;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int calculate() {
        return helper(value, 2 * value);
    }
}

class WithStaticMethods {

    private int value;

    private static int helper(int a, int b) {
        return a * b + 1;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int calculate() {
        return helper(value, 2 * value);
    }
}

Les lignes qui nous intéressent sont les appels à l' helper(...) sur les classes WithoutStaticMethods et WithStaticMethods.

Sans méthodes statiques

Dans le premier cas, sans méthodes statiques, lorsque vous appelez la méthode d'assistance à la JVM doit pousser la référence à l'instance de la transmettre à l' invokespecial. Jetez un coup d'oeil au code de l' calculate() méthode:

 0 aload_0
 1 aload_0
 2 getfield #2 <app/WithoutStaticMethods.value>
 5 iconst_2
 6 aload_0
 7 getfield #2 <app/WithoutStaticMethods.value>
10 imul
11 invokespecial #3 <app/WithoutStaticMethods.helper>
14 ireturn

L'instruction à 0 (ou 1), en aload_0, va charger la référence à l'instance sur la pile, et il sera utilisé plus tard par invokespecial. Cette instruction va mettre cette valeur en tant que premier paramètre de l' helper(...) de la fonction, et il n'est jamais utilisé, comme nous pouvons le voir ici:

0 iload_1
1 iload_2
2 imul
3 iconst_1
4 iadd
5 ireturn

Voir il n'y a pas d' iload_0? Il a été chargé inutilement.

Avec des méthodes statiques

Maintenant, si vous déclarez la méthode d'assistance, statique, puis l' calculate() méthode ressemblera à:

 0 aload_0
 1 getfield #2 <app/WithStaticMethods.value>
 4 iconst_2
 5 aload_0
 6 getfield #2 <app/WithStaticMethods.value>
 9 imul
10 invokestatic #3 <app/WithStaticMethods.helper>
13 ireturn

Les différences sont:

  • il y a un moins d' aload_0 enseignement
  • la méthode d'assistance est maintenant appelé avec invokestatic

Ainsi, le code de la fonction d'assistance est également un peu différent: il n'y a pas d' this comme premier paramètre, les paramètres sont à des positions 0 et 1, comme on peut le voir ici:

0 iload_0
1 iload_1
2 imul
3 iconst_1
4 iadd
5 ireturn

Conclusion

De la conception du code de l'angle, il fait beaucoup plus de sens pour déclarer l'aide de la méthode statique: le code parle de lui-même, il contient les informations les plus utiles. Il affirme qu'il n'a pas besoin de l'état de l'instance de travail.

Au niveau du bytecode, il est beaucoup plus claire de ce qui se passe, et il n'est pas inutile de code (que, bien que je crois que l'équipe n'a aucun moyen de l'optimiser, n'entraînerait pas de façon significative les performances de coût).

16voto

Jay Points 14781

Si une méthode ne permet pas d'utiliser les données de l'instance, alors il doit être statique. Si la fonction est public, cela vous donnera l'important efficacité du coup de pouce que vous n'avez pas besoin de créer un superflu instance de l'objet juste pour appeler la fonction. Probablement le plus important, c'est de l'auto-documentation avantage: en déclarant la fonction statique, vous télégraphe au lecteur que cette fonction n'utilise pas les données de l'instance.

Je ne comprends pas le sentiment de beaucoup d'affiches ici, il y a quelque chose de mal à avoir des fonctions statiques dans un programme Java. Si une fonction est logiquement statique, de la rendre statique. La bibliothèque Java a de nombreuses fonctions statiques. La classe Math est assez bien rempli avec des fonctions statiques.

Si j'ai besoin, par exemple, une fonction pour calculer une racine carrée, le rationnel façon de le faire serait:

public class MathUtils
{
  public static float squareRoot(float x)
  {
    ... calculate square root of parameter x ...
    return root;
  }
}

Bien sûr, vous pourriez faire un "plus OOPy" version qui ressemblait à ceci:

public class MathUtils
{
  private float x;
  public MathUtils(float x)
  {
    this.x=x;
  }
  public float squareRoot()
  {
    ... calculate square root of this.x ...
    return root;
  }
}

Mais à côté de réunion abstraite objectif de l'utilisation de la programmation orientée objet, lorsque cela est possible, comment cela serait-il mieux? Il faut plus de lignes de code, et il est moins flexible.

(Et oui, j'ai il y a maintenant une fonction racine carrée dans le standard de la classe de Mathématiques. J'étais juste l'utilisation de ce comme un exemple utile.)

Si le seul endroit une fonction statique est utilisée et est tous susceptible d'être utilisé est de l'intérieur d'une certaine classe, alors oui, faire un membre de cette classe. Si elle fait aucun sens de l'appeler à partir de l'extérieur de la classe, le rendre privé.

Si une fonction statique est logiquement associé à une classe, mais peut raisonnablement être appelé de l'extérieur, puis en faire une public static. Comme, de Java parseInt fonction est dans la classe Integer parce qu'il a à faire avec des entiers, de sorte que c'était rationnelle de la place pour le mettre.

D'autre part, il arrive souvent que vous écrivez une classe et vous vous rendez compte que vous avez besoin de quelques statique de la fonction, mais la fonction n'est pas vraiment liée à cette classe. C'est juste la première fois il vous est arrivé de réaliser vous en avez besoin, mais il pourrait tout à fait rationnellement être utilisé par d'autres classes qui n'ont rien à voir avec ce que vous faites maintenant. Comme, pour revenir à la racine carrée exemple, si vous avez eu un "Lieu" de la classe qui comprenait la latitude et la longitude, et que vous voulez une fonction pour calculer la distance entre deux lieux et vous avez besoin d'une racine carrée dans le cadre du calcul, (et faire semblant il n'y a pas de fonction racine carrée disponible dans la bibliothèque standard), il ferait beaucoup de sens de créer une fonction racine carrée plutôt que d'intégrer cela dans votre plus grande logique. Mais il n'appartient pas vraiment à votre Place de la classe. Ce serait un temps de créer une catégorie distincte pour les "maths utilitaires" ou quelque chose du genre.

Demandez-vous, "Devrait foo toujours être statique, indépendamment de toute autre considération?" Je dis "Presque, mais pas tout à fait."

La seule raison pour laquelle je peux penser à faire pas statique serait le cas d'une sous-classe veut le remplacer.

Je ne vois pas d'autres raisons, mais je ne voudrais pas exclure la possibilité. Je suis réticent à dire "jamais, jamais, jamais, sous aucun prétexte" parce que quelqu'un peut généralement venir avec quelques cas particulier.

8voto

BlairHippo Points 2849

Question intéressante. Dans la pratique, je ne vois pas l'intérêt de rendre la classe A's helper privées méthodes statiques (sauf s'ils sont liés à un public accessible méthode statique en A, bien sûr). Vous n'êtes pas gagner quoi que ce soit-par définition, une méthode qui pourrait avoir besoin d'eux en a déjà une instance de A à sa disposition. Et depuis qu'ils sont derrière-le-scènes méthodes d'assistance, il n'y a rien à dire que vous (ou un autre co-travailleur) ne sont pas finalement décider de l'une de ces apatrides aides pourrait en fait l'avantage de savoir à l'état, ce qui pourrait conduire à un peu de refactoring de nuisance.

Je ne pense pas que c'est mal de se retrouver avec un grand nombre d'internes des méthodes statiques, mais je ne vois pas quel est l'avantage de vous en tirer. Je dis par défaut à non-statique, sauf si vous avez une bonne raison de ne pas.

8voto

delnan Points 52260

Pas de. Jamais. Méthodes statiques devraient être une exception. OO est tout au sujet d'avoir des Objets avec des comportements qui tourne autour de l'état de l'objet. À mon humble avis, dans l'idéal, il ne devrait pas y avoir (ou très peu) les méthodes statiques, car tout sans rapport avec l'état de l'objet pourrait (et pour éviter de diriger le concept d'un objet jusqu'à l'absurde, devraient) être placé dans une plaine ancienne fonction au niveau du module. Exception Possible pour les usines parce que Complexe.fromCartesian (pour prendre un wikipédia exemple) lit si bien.

Bien sûr, ce (edit: Module-fonctions de niveau) n'est pas possible dans un seul paradigme OO langue (edit: comme Java) - c'est pourquoi je suis un fervent défenseur de la multi-paradigme de conception de langage, par la manière. Mais même dans une langue exclusivement OO, la plupart des méthodes tournera autour de l'état de l'objet et, par conséquent, être non statiques. C'est, à moins que votre conception n'a rien à voir avec OO - mais dans ce cas, vous utilisez la mauvaise langue.

5voto

Bill K Points 32115

En général je n'ai pas statique, mais devrait probablement. Il est précieux comme un soupçon de dire à la prochaine codeur que cette méthode CANT modifier l'état de votre objet, et il est précieux pour vous donner un avertissement lorsque vous modifiez la méthode pour accéder à un membre que vous sont en train de changer la nature de la méthode.

Le codage est tout au sujet de la communication avec la prochaine codeur--ne vous inquiétez pas au sujet de faire le code à exécuter, c'est trivial. Afin de maximiser la communication, je dirais que si vous avez vraiment besoin d'une telle aide, le rendant statique est une excellente idée. Rendre privé est essentiel de trop, sauf si vous effectuez une des Mathématiques. comme la classe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X