Pourquoi / pourquoi Java doit-il avoir des void
méthodes? Référence :
Toute méthode déclarée vide ne renvoie pas de valeur.
Autant que je sache, chaque utilisation de void
serait mieux servie en renvoyant un indicateur d'état, l'objet invoqué ou null
.
Cela ferait de chaque appel une instruction assignable et faciliterait les modèles de constructeur et l’enchaînement des méthodes. Les méthodes qui ne sont appelées que pour leurs effets renvoient généralement un type booléen ou générique Success
ou lèvent une exception en cas d'échec.
java
programming-languages
return-type
marisbest2
la source
la source
Réponses:
Parce qu'il y a une différence entre "Cette fonction peut réussir ou échouer et est suffisamment consciente d'elle-même pour pouvoir faire la différence" et "Il n'y a pas de retour d'information sur l'effet de cette fonction". Sans cela
void
, vous vérifieriez sans cesse les codes de réussite et croiriez que vous écrivez un logiciel robuste, alors que vous ne faites rien de la sorte.la source
void
ne dit rien sur le point de savoir si la méthode ou la fonction est suffisamment consciente de soi pour pouvoir être lancée de manière appropriée.void
type, et Java a été conçu pour suivre de nombreuses conventions de la famille de langage C.Success
type générique " de toute façon? En fait, les valeurs renvoyées pour indiquer le succès sont encore moins importantes en Java qu'en C, car Java comporte des exceptions pour indiquer un échec, contrairement au C.la source
Void
type de @SargeBorsch Java agit comme un type d'unité (par exemple, pour les génériques), bien qu'il soit tristement différent devoid
(remarque: un chaton câlin meurt chaque fois que vous inventez un nouveau type pour corriger le type que vous aviez foiré dans la version précédente). Si quelqu'un ne connaît pas des types d' unité, ceci est une intro décent: en.wikipedia.org/wiki/Unit_typenull
(en fait, c'est le seul choix), mais null est une chose spéciale, toute valeur de type référence en Java peut être nulle (ceci est une autre erreur dans la conception du langage). Et, comme je l’ai dit plus tôt, si vous utilisez leVoid
type de retour au lieu devoid
mark, le compilateur Java n’est pas votre ami.null
. Le fait qu’ilnull
s’agisse d’un membre de la plupart des types n’a aucune incidence sur le fait qu’il s’agisseVoid
ou non d’un type d’unité.La raison initiale pour laquelle le langage a un
void
type est parce que, comme dansC
, les créateurs du langage ne voulaient pas compliquer inutilement la syntaxe du langage avec des procédures et des fonctions identiques à celles de Pascal.C'était la raison initiale.
Vos suggestions:
C'est un non-non. Nous n'utilisons pas d'indicateurs d'état. Si quelque chose ne va pas, nous le signalons via des exceptions.
Le style courant des invocations est un développement récent. La plupart des programmeurs qui utilisent très bien couramment aujourd'hui et qui roulent des yeux s’ils doivent utiliser une interface qui ne la prend pas en charge ne sont même pas nés de la création de Java.
Cela vous obligerait à déclarer une méthode comme renvoyant quelque chose, alors qu'en réalité, elle ne renvoie rien. Cela serait donc très déroutant pour quelqu'un qui cherche une interface à essayer de comprendre ce qu'elle fait. Les gens inventeraient inévitablement une classe par ailleurs inutile, qui signifie "aucune valeur de retour", de sorte que toutes les fonctions qui n'ont rien à renvoyer puissent renvoyer une référence nulle à une telle classe. Ce serait maladroit. Heureusement, il existe une solution à cela, il s'appelle
void
. Et c'est la réponse à votre question.la source
int
. Un mot-clé a donc été ajouté à la suite de K & R pour indiquer «aucun type de retour».Certaines méthodes, comme
System.out.println
ne retourne rien d’utile, mais s’appelle purement pour cet effet secondaire.void
est un indicateur utile pour le compilateur et pour le lecteur de code qu'aucune valeur utile n'est renvoyée.Retourner
null
au lieu devoid
signifie que vous obtiendrez simplementNullPointerException
le moment où vous utiliserez cette valeur pour quoi que ce soit. Donc, vous négociez une erreur de compilation pour une erreur d’exécution qui est bien pire. De plus, vous devrez définir le type de retour commeObject
étant trompeur et source de confusion. (Et l'enchaînement ne fonctionnerait toujours pas.)Les codes d'état sont généralement utilisés pour indiquer des conditions d'erreur, mais Java a des exceptions à cette fin.
Renvoyer
this
n'est pas possible à partir de méthodes statiques.Renvoyer un
Success
objet générique n'aurait aucun but utile.la source
L' une des raisons est qu'il peut être trompeur de revenir jamais autre chose que, par exemple,
null
. Exemple:Que devrait
Arrays.sort(a)
revenir?Si vous soutenez que cela
a
doit être renvoyé afin que l'appel puisse être chaîné (ce qui semble être votre réponse d'après votre question), il n'est alors plus clair si la valeur renvoyée est une copie de l'objet d'origine ou de l'objet d'origine lui-même. . Les deux sont possibles. Et oui, vous pouvez le mettre dans la documentation, mais c'est suffisamment ambigu pour ne pas créer d'ambiguïté.D'autre part, si vous soutenez que cela
null
devrait être renvoyé, cela soulève la question de savoir quelle information la valeur renvoyée fournit éventuellement à l'appelant et pourquoi le programmeur devrait être obligé d'écrirereturn null
lorsqu'il ne transmet aucune information.Et si vous revenez quelque chose d' autre tout à fait absurde (comme la longueur
a
), il fait juste utiliser cette valeur de retour vraiment déroutant - il suffit de penser combien plus confondant est - à - dire auint len = Arrays.sort(a)
lieu deint len = A.length
!la source
return null;
- la machine virtuelle Java pourrait tout aussi bien que si le mandat de contrôle tombe à la fin d'une fonction par autre qu'une explicitereturn
outhrow
déclaration,null
est implicitement renvoyé à l'appelant. IIRC C fait cela, sauf que la valeur de retour n'est pas définie dans ce cas (ce sera quelle que soit la valeur qui se trouve à l'emplacement utilisé pour la valeur de retour à ce moment-là).return
instruction. Au lieu de cela, vous obtenez une erreur du compilateur vous informant de votre erreur. Insertion d'un implicitereturn null;
serait mieux que "comportement indéfini", mais pas beaucoup. Cela ne serait utile que lorsque le type de retour n'a pas de sens, mais d'où le compilateur tire-t-il la conclusion que la valeur de retour n'a pas de sens, quand ce n'est pas le casvoid
?return
cela n'ajoute vraiment aucune valeur…», eh bien, comme dit, il n'y a aucun indicateur pour le compilateur qu'un retour n'apporterait aucune valeur s'il n'y avait pas devoid
type. C'est en fait le contraire. La première hypothèse est qu'une méthode déclarant un type de retour veutreturn
quelque chose d'utile de ce type. Et nous n'avons pas encore parlé de types primitifs, qui n'ont pas denull
valeur. Par conséquent, toute valeur par défaut injectée par le compilateur entrerait en conflit avec la plage de valeurs de retour potentiellement utiles.Renvoyer un
boolean
qui est toujours égal àtrue
ce que vous suggérez est non seulement inutile (la valeur de retour ne contient aucune information), mais serait en réalité trompeur. La plupart du temps, il est préférable d'utiliser les types de retour qui ne portent que le plus d' informations est en fait disponible - c'est pourquoi en Java que vous avezboolean
pourtrue
/false
plutôt que de retourner unint
avec 4 milliards de valeurs possibles. De même, renvoyer unboolean
avec deux valeurs possibles où il n'y a qu'une seule valeur possible ("succès générique") serait trompeur.Cela ajouterait également une surcharge de performances inutile.
Si une méthode est utilisée uniquement pour ses effets secondaires, il n'y a rien à renvoyer, et le type de retour
void
reflète exactement cela. Les rares erreurs potentielles peuvent être signalées via des exceptions.Une chose qui pourrait être améliorée, serait de créer
void
un type réel, tel que celui de ScalaUnit
. Cela résoudrait certains problèmes tels que la gestion des génériques.la source
List.add
revient toujourstrue
, mais c'est pour être compatible avec le contrat plus large deCollection.add
,Set.add
peut donc revenirtrue
oufalse
.Java est une langue relativement ancienne. Et en 1995 (date de sa création) et peu de temps après, les programmeurs étaient très préoccupés par la durée pendant laquelle un processus prenait le contrôle du processeur ainsi que la consommation de mémoire. Le renvoi de vide éliminerait quelques cycles d'horloge et un peu de consommation de mémoire d'un appel de fonction, car vous n'auriez pas à mettre la valeur de retour sur la pile et vous ne seriez pas obligé de la supprimer par la suite.
Un code efficace ne vous restitue pas quelque chose que vous n'utiliseriez jamais. Par conséquent, mettre vide dans un objet qui a une valeur de retour sans signification est une bien meilleure pratique que de renvoyer une valeur de succès.
la source
J'ai lu des arguments qui suggèrent que la deuxième option (retour
this
) devrait être l'approche au lieu devoid
. C'est une bonne idée, mais l'approche de type constructeur n'était pas populaire au moment de la création de Java. Si c'était aussi populaire à l'époque que maintenant, c'est peut-être l'approche qui a été adoptée. Revenirnull
est une très mauvaise idée, OMI. Je souhaitenull
n'était même pas dans la langue du tout.Le problème est maintenant que si une méthode retourne une instance de son propre type, il n'est pas clair s'il s'agit d'un nouvel objet ou du même objet. Souvent, cela n'a pas d'importance (ou ne devrait pas l'être), mais d'autres fois, cela compte. Je suppose que le langage pourrait être modifié pour revenir implicitement
this
sur les méthodes void. Le seul problème auquel je peux penser pour le moment est que si la méthode était modifiée ultérieurement pour renvoyer un nouvel objet du même type, il n'y aurait pas d'avertissement de compilation, mais ce n'est peut-être pas grave. Le système de types actuel ne se soucie pas de ces types de changements maintenant. La manière dont cela interagit avec l'héritage / les interfaces nécessiterait une certaine réflexion, mais permettrait également aux anciennes API sans style constructeur d'être appelées comme si elles le faisaient.la source
null
ne faisaient pas partie du langage, les gens utiliseraient toutes sortes de valeurs sentinelles qui signifient "ignorez cet argument / cette valeur de retour, il ne contient aucune valeur sensible". Le problème avecnull
n'est pas la chose elle-même, mais seulement qu'elle a tendance à être utilisée de manière incorrecte. Je parierais que ce problème ne serait exagéré que si la normenull
était remplacée par une multitude de solutions personnalisées, dans lesquelles chaque implémentation se comporterait différemment, comme en ignorant silencieusement l'utilisation ou en lançant des exceptions spéciales au lieu d'une exception standart null pointer, etc.null
un type optionnel approprié (commeMaybe
dans Haskell). Le problème avec les valeurs NULL en Java est qu’il n’ya pas de moyen sensé de décider immédiatement si une valeur est nullable en pratique ou non. Cela entraîne à la fois une programmation inutilement défensive (recherche de valeurs nulles là où c'est inutile, augmentant ainsi le pourcentage de caca dans le code) et de NPE accidentels en production (si on oublie de vérifier où cela était nécessaire). Oui, cela est partiellement résolu par les annotations mais elles sont facultatives, pas toujours cochées, etc. Elles ne vous sauveront donc pas aux limites avec du code tiers.null
fonctionne très bien pour cela (fin = simple), mais les valeurs optionnelles normalisées avec une sémantique solide sont définitivement une autre bonne option (fin = sans danger).Un autre aspect:
Java est un langage statique avec des fonctionnalités assez strictes. Cela signifie que beaucoup de choses qui seraient assez ouvertes ou dynamiques dans d'autres langues (c / f Ruby, Lisp, etc.) sont strictement déterminées.
Ceci est une décision de conception générale. Il est difficile de répondre au "pourquoi" (enfin, car les concepteurs de la langue ont pensé que ce serait bien!). Le "pour quoi" est assez clair: il permet au compilateur de détecter beaucoup d'erreurs, ce qui est généralement une très bonne fonctionnalité pour toutes les langues. Deuxièmement, il est relativement facile de raisonner sur la langue. Par exemple, il est relativement facile de créer des preuves de correction formelles dans (des sous-ensembles de) le langage Java; à titre de comparaison, cela serait pratiquement impossible dans un langage dynamique comme Ruby et al.
Cette pensée imprègne le langage, par exemple, la déclaration forcée d'exceptions possibles qu'une méthode peut générer, le type séparé de
interface
vsclass
pour éviter un héritage multiple ambigu, etc. Pour ce qu’il est (langage du monde réel impératif statique et axé sur la gestion des erreurs de compilation), ces éléments sont en fait assez élégants et puissants. Ils se rapprochent des langages théoriques (scientifiques) qui sont conçus exprès pour explorer certaines de ces questions plus que tout autre langage du monde réel auparavant (à ce moment-là, pensez-vous).Alors. Avoir un
void
type strict est un message clair: cette méthode ne retourne rien, point. C'est ce que c'est. Le remplacer par l'application forcée de toujours renvoyer quelque chose mènerait soit à un comportement beaucoup plus dynamique (comme en Ruby où chaque def a une valeur de retour explicite ou implicite, toujours), ce qui serait mauvais pour la prouvabilité et le raisonnement; ou à gonfler massif en utilisant un autre mécanisme ici.(Et NB, Ruby (par exemple) gère différemment, et sa solution est toujours exactement comme acceptable que de Java, car il a une philosophie complètement différente. Par exemple , il jette prouvabilité et raisonnabilité complètement hors de la fenêtre tout en mettant un grand accent sur extrêmement haute expressivité de la langue.)
la source