Нужно ли / почему Java иметь void
методы? Ссылка :
Любой метод, объявленный как void, не возвращает значение.
Насколько я могу судить, каждое использование void
было бы лучше обслуживать, возвращая флаг состояния, вызываемый объект или null
.
Это сделало бы каждый вызов оператором, который можно назначить, и упростил бы шаблоны компоновщика и цепочку методов. Методы, которые вызываются только для их эффектов, обычно возвращают логический или универсальный Success
тип или генерируют исключение при сбое.
java
programming-languages
return-type
marisbest2
источник
источник
Ответы:
Потому что есть разница между «Эта функция может быть успешной или неуспешной и достаточно самосознательна, чтобы она могла отличить» и «Нет отзывов об эффекте этой функции». Без
void
этого вы бы бесконечно проверяли коды успеха и полагали, что вы пишете надежное программное обеспечение, хотя на самом деле вы ничего не делаете.источник
void
ничего не говорит о том, достаточно ли самодостаточен метод или функция, чтобы бросить в зависимости от ситуации.void
тип, а Java был разработан, чтобы следовать многим соглашениям семейства языков C.Success
типом» в любом случае? Фактически, возвращаемые значения, указывающие на успех, в Java даже менее важны, чем в C, потому что Java имеет исключения, указывающие на сбой, а C - нет.источник
Void
тип действует как тип Unit (например, для Generics), но, к сожалению, он отличается отvoid
(примечание: приятный котенок умирает каждый раз, когда вы изобретаете новый тип, чтобы исправить тип, который вы испортили в предыдущей версии). Если кто-то не знаком с типами юнитов, этоnull
(на самом деле это единственный выбор), но ноль - это особая вещь, любое значение ссылочного типа в Java может быть нулевым (это еще одна ошибка в проектировании языка). И, как я уже говорил ранее, если вы используетеVoid
тип возврата вместоvoid
mark, компилятор Java не ваш друг.null
. Тот факт, что онnull
является членом большинства типов, не имеет отношения к тому,Void
является ли это типом единицы.Оригинальная причина , почему язык имеет
void
тип, потому что , как и вC
, создатели языка не хотят излишне усложнить синтаксис языка с процедурой s и функция ы пути Паскаль сделал.Это была первоначальная причина.
Твои предложения:
Это нет-нет. Мы не используем статусные флаги. Если что-то идет не так, мы сообщаем об этом через исключения.
Свободный стиль вызовов - недавняя разработка. Многие из программистов, которые сегодня с радостью используют свободное владение языком и закатывают глаза, если им когда-либо приходится использовать интерфейс, который его не поддерживает, даже не были рождены при создании Java.
Это вынудит вас объявить метод как возвращающий что-то, когда на самом деле он ничего не возвращает, так что это будет очень запутанным для того, кто смотрит на интерфейс, пытаясь понять, что он делает. Люди неизбежно придумают какой-то бесполезный в противном случае класс, который будет означать «нет возвращаемого значения», чтобы все функции, которым нечего возвращать, могли возвращать нулевую ссылку на такой класс. Это было бы неуклюже. К счастью, есть решение для этого, это называется
void
. И это ответ на ваш вопрос.источник
int
, поэтому ключевое слово было добавлено после K & R для указания «возвращаемого типа».Некоторые методы, вроде
System.out.println
, не возвращают ничего полезного, но вызываются исключительно для этого побочного эффекта.void
является полезным индикатором для компилятора и читателя кода, что никакое полезное значение не возвращается.Возврат
null
вместоvoid
означает, что вы просто получитеNullPointerException
момент, когда вы используете это значение для чего-либо. Таким образом, вы обмениваете ошибку времени компиляции на ошибку времени выполнения, которая намного хуже. Кроме того, вы должны будете определить тип возвращаемого значения какObject
, что будет вводить в заблуждение и сбивать с толку. (И цепочка все равно не сработает.)Коды состояния обычно используются для указания условий ошибки, но Java имеет исключения для этой цели.
Возврат
this
невозможен из статических методов.Возвращение универсального
Success
объекта не имело бы никакой полезной цели.источник
Одна из причин заключается в том, что вводить в заблуждение что-либо, кроме, скажем, неверно
null
. Пример:Что должно
Arrays.sort(a)
вернуться?Если вы утверждаете, что
a
должен быть возвращен, чтобы вызов мог быть прикован цепью (что, по-видимому, является вашим ответом, исходя из вашего вопроса), то уже неясно, является ли возвращаемое значение копией исходного объекта или самого исходного объекта. , Оба возможны. И да, вы могли бы поместить это в документацию, но это достаточно неоднозначно, что вы не должны создавать двусмысленность в первую очередь.С другой стороны, если вы утверждаете, что
null
должно быть возвращено, возникает вопрос о том, какую информацию возвращаемое значение, возможно, предоставляет вызывающей стороне, и почему программист должен быть вынужден писать,return null
когда он не передает никакой информации.И если вы возвращаете что-то совершенно абсурдное (например, длину
a
), то это просто сбивает с толку использование этого возвращаемого значения - просто подумайте, насколько более запутанным будет сказатьint len = Arrays.sort(a)
вместоint len = A.length
!источник
return null;
- JVM также может предписывать, что если управление выходит за пределы функции, отличной от явногоreturn
илиthrow
оператора,null
неявно возвращается вызывающей стороне. IIRC C делает это, за исключением того, что возвращаемое значение в этом случае не определено (это будет любое значение, которое будет в местоположении, используемом для возвращаемого значения в данный момент).return
утверждение. Вместо этого вы получаете ошибку компилятора, сообщающую о вашей ошибке. Вставка неявногоreturn null;
было бы лучше, чем «неопределенное поведение», но не намного. Это было бы полезно только в том случае, если возвращаемый тип не имеет значения, но откуда компилятор делает вывод, что возвращаемое значение не имеет значения, если это не такvoid
?return
действительно не добавляет никакого значения…», ну, как уже говорилось, для компилятора нет индикатора, что возвращение не добавит никакого значения, если нетvoid
типа. На самом деле все наоборот, первое предположение состоит в том, что метод, объявляющий возвращаемый тип, хочетreturn
чего-то полезного этого типа. И мы еще не говорили о примитивных типах, у которых нетnull
значения, следовательно, любое значение по умолчанию, введенное компилятором, будет конфликтовать с диапазоном потенциально полезных возвращаемых значений.Возвращать a,
boolean
всегда равное тому,true
которое вы предлагаете, не только бессмысленно (возвращаемое значение не несет никакой информации), но на самом деле вводит в заблуждение. Большую часть времени, то лучше использовать типы возвращения , которые только несут столько информации , сколько на самом деле доступны - вот почему в Java у вас естьboolean
дляtrue
/ ,false
а не возвращаяint
с 4 миллиардов возможных значений. Аналогично, возвращение aboolean
с двумя возможными значениями, в которых есть только одно возможное значение («общий успех»), будет вводить в заблуждение.Это также добавило бы ненужные потери производительности.
Если метод используется только для побочного эффекта, возвращать нечего, и тип возвращаемого значения
void
отражает именно это. Потенциальные редкие ошибки могут сигнализироваться через исключения.Одной вещью, которая может быть улучшена, будет создание
void
фактического типа, такого как ScalaUnit
. Это решило бы некоторые проблемы, такие как обработка дженериков.источник
List.add
всегда возвращаетсяtrue
, но это для совместимости с более широким контрактомCollection.add
, поэтомуSet.add
может вернутьсяtrue
илиfalse
.Ява - относительно старый язык. А в 1995 году (когда он был создан) и вскоре после этого программисты были очень обеспокоены количеством времени, которое процесс взял под контроль процессора, а также потреблением памяти. Возврат void устранит несколько тактов и немного потребления памяти при вызове функции, потому что вам не нужно будет помещать возвращаемое значение в стек, и вам впоследствии не придется его удалять.
Эффективный код не возвращает вам то, что вы никогда бы не использовали, и, следовательно, пустота в нечто, имеющее бессмысленное возвращаемое значение, является гораздо лучшей практикой, чем возвращение успешного значения.
источник
Я прочитал аргументы, которые предполагают, что второй вариант (возврат
this
) должен быть подход вместоvoid
. Это довольно хорошая идея, но подход в стиле конструктора не был популярен во время создания Java. Если бы это было так же популярно в то время, как и сейчас, возможно, таков подход. Возвращениеnull
- это действительно плохая идея ИМО. Хотелось быnull
даже не на языке вообще.Проблема в том, что если метод возвращает экземпляр своего собственного типа, неясно, является ли это новым объектом или тем же самым. Часто это не имеет (или не должно) иметь значение, но в других случаях это имеет значение. Я полагаю, что язык можно изменить, чтобы неявно возвращаться
this
к пустым методам. Единственная проблема, о которой я могу подумать в данный момент, заключается в том, что если бы метод был позже изменен для возврата нового объекта того же типа, не было бы предупреждений компиляции, но это, возможно, не имеет большого значения. Нынешняя система типов не заботится об этих типах изменений сейчас. То, как это взаимодействует с наследованием / интерфейсами, потребует некоторого рассмотрения, но это позволило бы легко вызывать старые API без стиля конструктора, как если бы они это делали.источник
null
они не были частью языка, люди использовали бы все виды дозорных значений, которые означают «пожалуйста, игнорируйте этот аргумент / возвращаемое значение, оно не содержит никакого разумного значения». Проблемаnull
не в самой вещи, а в том, что она используется неправильно. Держу пари, что эта проблема будет только преувеличена, если стандартизированныйnull
будет заменен несметным числом пользовательских решений, где каждая реализация будет вести себя по-разному, как молчаливое игнорирование использования, или выбрасывать специальные исключения вместо стандартного исключения нулевого указателя и т. Д.null
является правильный необязательный тип (например,Maybe
в Haskell). Проблема с нулями в Java состоит в том, что нет никакого здравого способа немедленно решить, является ли значение обнуляемым на практике или нет. Это приводит к обоим из: излишне защитному программированию (проверка на нули, где это бессмысленно, увеличивая тем самым процент корма в коде), и случайным NPE в производстве (если забыли проверить, где это было необходимо). Да, это частично решается аннотациями, но они являются необязательными, не всегда проверяются и т. Д. Таким образом, они не спасут вас на границах с сторонним кодом.null
отлично работает для этого (отлично = просто), но стандартизированные необязательные значения с твердой семантикой, безусловно, еще один хороший вариант (хорошо = безопасно).Еще один аспект:
Java - это статический язык с довольно строгими возможностями. Это означает, что многие вещи, которые были бы достаточно открыты или динамичны в других языках (c / f Ruby, Lisp и т. Д.), Строго определены.
Это общее дизайнерское решение. На «почему» сложно ответить (ну, потому что разработчики языка думали, что это будет хорошо!). «Зачем» довольно ясно: он позволяет компилятору обнаруживать множество ошибок, что, как правило, довольно хорошая функция для любого языка. Во-вторых, это сравнительно легко рассуждать о языке. Например, относительно легко создать формальную корректность, доказывающую в (подмножествах) язык Java; для сравнения, это было бы практически невозможно в динамическом языке, таком как Ruby et al.
Это мышление пронизывает язык, например, принудительное объявление возможных исключений, которые может выдавать метод, отдельный тип
interface
vs.,class
чтобы избежать неоднозначного множественного наследования, и так далее. Для чего это (статический императивный язык ООП реального мира с упором на обработку ошибок во время компиляции) эти вещи на самом деле довольно элегантны и мощны. Они приближаются к теоретическим (научным) языкам, которые специально созданы для того, чтобы исследовать некоторые из этих вопросов, чем любой другой язык реального мира (в то время, учтите).Так. Наличие строгого
void
типа - ясное сообщение: этот метод ничего не возвращает, точка. Что есть, то есть. Замена его принудительным постоянным возвратом чего-либо привела бы к гораздо более динамичному поведению (как в Ruby, где каждое определение всегда имеет явное или неявное возвращаемое значение), что было бы плохо для доказуемости и рассуждений; или к огромному раздутию, используя какой-то другой механизм здесь.(И NB, Ruby (например) обрабатывает это по-другому, и его решение все еще точно так же приемлемо, как и у Java, потому что у него совершенно иная философия. Например, оно полностью исключает доказуемость и разумность, одновременно уделяя большое внимание чрезвычайно высокая выразительность языка.)
источник