/ Por que o Java precisa ter void
métodos? Referência :
Qualquer método declarado nulo não retorna um valor.
Tanto quanto posso pensar, todo uso de void
seria melhor se retornássemos uma flag de status, o objeto que está sendo chamado ou null
.
Isso tornaria cada chamada uma declaração que é atribuível e facilitaria os padrões do construtor e o encadeamento de métodos. Métodos que são chamados apenas para seus efeitos geralmente retornam um tipo booleano ou genérico Success
ou lançam uma exceção em caso de falha.
java
programming-languages
return-type
marisbest2
fonte
fonte
Respostas:
Como existe uma diferença entre "Esta função pode ter êxito ou falhar e é autoconsciente o suficiente para saber a diferença" e "Não há comentários sobre o efeito dessa função". Sem isso
void
, você verifica incessantemente os códigos de sucesso e acredita que está escrevendo um software robusto, quando na verdade não está fazendo nada disso.fonte
void
não diz nada sobre se o método ou função é autoconsciente o suficiente para ser lançado conforme apropriado.void
tipo e Java foi projetado para seguir muitas das convenções da família de idiomas C.Success
tipo genérico "? De fato, os valores de retorno para indicar sucesso são ainda menos importantes em Java do que em C, porque Java possui exceções para indicar falha e C não.fonte
Void
tipo de Java atua como um tipo de unidade (por exemplo, para genéricos), embora, infelizmente, seja diferente devoid
(nota lateral: um gatinho fofo morre toda vez que você inventa um novo tipo para corrigir o tipo que você errou na versão anterior). Se alguém não está familiarizado com os tipos de unidade, esta é uma introdução decente: en.wikipedia.org/wiki/Unit_typenull
(na verdade, essa é a única opção), mas nulo é uma coisa especial, qualquer valor do tipo de referência em Java pode ser nulo (esse é outro erro no design da linguagem). E, como eu disse anteriormente, se você estiver usando oVoid
tipo de retorno em vez davoid
marca, o compilador Java não é seu amigo.null
. O fato denull
ser um membro da maioria dos tipos é irrelevante para saber seVoid
é um tipo de unidade.A razão original pela qual a linguagem tem um
void
tipo é porque, como emC
, os criadores da linguagem não queriam complicar desnecessariamente a sintaxe da linguagem com procedimentos e funções como Pascal.Essa foi a razão original.
Suas sugestões:
Isso é um não-não. Nós não usamos sinalizadores de status. Se algo der errado, nós o reportamos por meio de exceções.
O estilo fluente de invocações é um desenvolvimento recente. Muitos dos programadores que estão muito felizes em usar fluentemente hoje em dia e reviram os olhos se tiverem que usar uma interface que não a suporta nem nasceram quando o Java foi criado.
Isso forçaria você a declarar um método como retornando algo, quando na verdade ele não está retornando nada, portanto seria muito confuso para alguém que está olhando para uma interface tentando descobrir o que faz. As pessoas inevitavelmente inventariam alguma classe inútil que significa "sem valor de retorno", para que todas as funções que não têm nada a retornar possam retornar uma referência nula a essa classe. Isso seria desajeitado. Felizmente, existe uma solução para isso, é chamada
void
. E essa é a resposta para sua pergunta.fonte
int
, portanto, uma palavra-chave foi adicionada após K&R para indicar 'no return type'.Alguns métodos, como o
System.out.println
, não retornam nada útil, mas são chamados exclusivamente para esse efeito colateral.void
é um indicador útil para o compilador e para o leitor de código que nenhum valor útil é retornado.Retornar em
null
vez devoid
significa que você apenas obteriaNullPointerException
o momento em que usar esse valor para qualquer coisa. Então você troca um erro de tempo de compilação por um erro de tempo de execução que é muito pior. Além disso, você teria que definir o tipo de retorno comoObject
, o que seria enganoso e confuso. (E o encadeamento ainda não funcionaria.)Os códigos de status geralmente são usados para indicar condições de erro, mas o Java possui exceções para essa finalidade.
this
Não é possível retornar de métodos estáticos.Retornar um
Success
objeto genérico não teria nenhum propósito útil.fonte
Uma razão é que pode ser enganoso retornar algo que não seja, digamos
null
,. Exemplo:O que deve
Arrays.sort(a)
retornar?Se você argumenta que
a
deve ser retornado para que a chamada possa ser encadeada (que parece ser sua resposta a julgar pela sua pergunta), não fica mais claro se o valor de retorno é uma cópia do objeto original ou o próprio objeto original . Ambos são possíveis. E sim, você pode colocá-lo na documentação, mas é suficientemente ambíguo que você não deve criar a ambiguidade em primeiro lugar.Por outro lado, se você argumenta que
null
deve ser retornado, isso levanta a questão de quais informações o valor de retorno possivelmente está fornecendo ao chamador e por que o programador deve ser forçado a escreverreturn null
quando não transmite informações.E se você retornar algo totalmente absurdo (como o tamanho de
a
), isso tornará o uso do valor de retorno realmente confuso - pense em quanto mais confuso é dizer emint len = Arrays.sort(a)
vez deint len = A.length
!fonte
return null;
- a JVM poderia também exigir que se o controle cair do final de uma função por outro caminho que não seja explícitoreturn
outhrow
declaração,null
seja implicitamente retornado ao chamador. O IIRC C faz isso, exceto que o valor de retorno é indefinido nesse caso (será o valor que estiver no local usado para o valor de retorno no momento).return
declaração. Em vez disso, você recebe um erro do compilador informando sobre seu erro. Inserir um implícitoreturn null;
seria melhor que "comportamento indefinido", mas não muito. Isso seria útil apenas quando o tipo de retorno não tem significado, mas de onde o compilador tira a conclusão de que o valor de retorno não tem significado, quando não évoid
?return
realmente não agregar valor ...”, bem, como foi dito, não há indicador para o compilador de que um retorno não acrescentaria valor, se não houver umvoid
tipo. Na verdade, é o contrário, a primeira suposição é que um método que declara um tipo de retorno desejareturn
algo útil desse tipo. E ainda não falamos sobre tipos primitivos, que não têmnull
valor, portanto, qualquer valor padrão injetado pelo compilador entraria em conflito com o intervalo de valores de retorno potencialmente úteis.Retornar um
boolean
que é sempre igual aotrue
que você sugere, não é apenas inútil (o valor de retorno não traz informações), mas seria realmente enganoso. Na maioria das vezes, é melhor usar tipos de retorno que só confiram tanta informação quanto está realmente disponível - é por isso que em Java você temboolean
paratrue
/false
em vez de retornar umint
com 4 bilhões de valores possíveis. Da mesma forma, retornar aboolean
com dois valores possíveis, onde existe apenas um valor possível ("sucesso genérico"), seria enganoso.Também acrescentaria sobrecarga de desempenho desnecessária.
Se um método é usado apenas para seu efeito colateral, não há nada para retornar e o tipo de retorno
void
reflete exatamente isso. Erros raros em potencial podem ser sinalizados por meio de exceções.Uma coisa que poderia ser melhorada seria criar
void
um tipo real, como o de ScalaUnit
. Isso resolveria alguns problemas, como lidar com genéricos.fonte
List.add
sempre retornatrue
, mas é por ser compatível com o contrato mais amplo deCollection.add
, portanto,Set.add
pode retornartrue
oufalse
.Java é uma linguagem relativamente antiga. E em 1995 (quando foi criado) e logo em seguida os programadores ficaram muito preocupados com a quantidade de tempo que um processo assumiu o controle do processador, bem como com o consumo de memória. Retornar nulo eliminaria alguns ciclos de clock e um pouco de consumo de memória de uma chamada de função, porque você não precisaria colocar o valor de retorno na pilha e não precisaria removê-lo posteriormente.
O código eficiente não devolve algo que você nunca usaria e, portanto, colocar o vazio em algo que tenha um valor de retorno sem sentido é uma prática muito melhor para se praticar do que retornar um valor de sucesso.
fonte
Eu li argumentos que sugerem que a segunda opção (retorno
this
) deve ser a abordagem em vez devoid
. Essa é uma boa idéia, mas a abordagem no estilo do construtor não era popular no momento em que o Java foi criado. Se fosse tão popular naquela época como agora, essa poderia ter sido a abordagem adotada. Retornarnull
é uma péssima idéia da OMI. Eu gostaria quenull
nem estivesse no idioma.O problema agora é que, se um método retorna uma instância do seu próprio tipo, não está claro se é um novo objeto ou o mesmo. Freqüentemente não importa (ou não deveria), mas outras vezes importa. Suponho que o idioma possa ser alterado para retornar implicitamente
this
aos métodos nulos. O único problema que posso pensar com isso no momento é que se o método fosse alterado posteriormente para retornar um novo objeto do mesmo tipo, não haveria avisos de compilação, mas talvez isso não seja um grande problema. O sistema de tipos atual não se preocupa com esses tipos de alterações agora. Como isso interage com a herança / interfaces precisaria de alguma consideração, mas permitiria que APIs antigas sem um estilo de construtor fossem facilmente chamadas como se fossem.fonte
null
não fizesse parte do idioma, as pessoas usariam todos os tipos de valores de sentinela que significam "por favor, ignore esse argumento / valor de retorno, ele não contém nenhum valor sensível". O problema comnull
não é a coisa em si, apenas que ela tende a ser usada incorretamente. Aposto que esse problema só seria exagerado se a padronizadanull
fosse substituída por uma infinidade de soluções personalizadas, em que cada implementação se comportaria de maneira diferente, como ignorar silenciosamente o uso ou lançar exceções especiais em vez de uma exceção padrão de ponteiro nulo etc.null
é um tipo opcional adequado (comoMaybe
em Haskell). O problema com nulos em Java é que não há uma maneira sã de decidir imediatamente se um valor é anulável na prática ou não. Isso leva a: programação desnecessariamente defensiva (verificação de nulos onde não faz sentido, aumentando assim a porcentagem de cocô no código) e NPEs acidentais na produção (se esqueceu de verificar onde era necessário). Sim, é parcialmente resolvido por anotações, mas são opcionais, nem sempre marcados, etc. Portanto, eles não o salvarão nos limites com código de terceiros.null
funciona bem para isso (fine = simple), mas valores opcionais padronizados com semântica sólida são definitivamente outra opção (fine = safe).Outro aspecto:
Java é uma linguagem estática com recursos bastante rígidos. Isso significa que muitas coisas que seriam bastante abertas ou dinâmicas em outros idiomas (c / f Ruby, Lisp etc.) são estritamente determinadas.
Esta é uma decisão geral de design. O "porquê" é difícil de responder (bem, porque os designers da linguagem pensaram que seria bom!). O "para quê" é bastante claro: permite que o compilador detecte muitos erros, o que geralmente é um recurso muito bom para qualquer idioma. Em segundo lugar, torna relativamente fácil raciocinar sobre o idioma. Por exemplo, é relativamente fácil criar provas formais de correção na (subconjuntos) da linguagem Java; como comparação, isso seria praticamente impossível em uma linguagem dinâmica como Ruby et al.
Esse pensamento permeia a linguagem, por exemplo, a declaração forçada de possíveis exceções que um método pode lançar, o tipo separado de
interface
vs.class
para evitar herança múltipla ambígua e assim por diante. Para o que é (uma linguagem imperativa estática do mundo real OOP, com forte foco no tratamento de erros em tempo de compilação), essas coisas são realmente bastante elegantes e poderosas. Eles se aproximam das linguagens teóricas (científicas) que são propositalmente criadas apenas para explorar alguns desses problemas do que qualquer outra linguagem do mundo real antes (naquele momento, lembre-se).Assim. Ter um
void
tipo estrito é uma mensagem clara: esse método não retorna nada, ponto final. É o que é. Substituí-lo pela aplicação para sempre retornar algo levaria a um comportamento muito mais dinâmico (como em Ruby, onde cada def tem sempre um valor de retorno explícito ou implícito), o que seria ruim para a provabilidade e o raciocínio; ou inchaço maciço usando algum outro mecanismo aqui.(E, no entanto, Ruby (por exemplo) lida com isso de maneira diferente, e sua solução ainda é exatamente tão aceitável quanto a de Java, porque possui uma filosofia completamente diferente. Por exemplo, lança a provabilidade e a razoabilidade completamente fora da janela enquanto coloca um grande foco em expressividade extremamente alta do idioma.)
fonte