Por que Java tem métodos 'void'?

52

Faz / por que o Java precisa ter void métodos? Referência :

Any method declared void doesn't return a value.

Até onde eu posso pensar, todo uso de void seria melhor servido retornando um sinalizador de status, o objeto sendo chamado ou null .

Isso faria de cada chamada uma declaração que fosse designável e facilitaria os padrões do construtor e o encadeamento de métodos. Os métodos que são chamados apenas para seus efeitos normalmente retornam um tipo booleano ou genérico de Success ou lançam uma exceção na falha.

    
por marisbest2 24.04.2017 / 16:09
fonte

9 respostas

159

Porque existe uma diferença entre "Esta função pode ter sucesso ou falhar e é autoconsciente o suficiente para poder dizer a diferença" e "Não há feedback sobre o efeito desta função". Sem void , você verificaria incessantemente os códigos de sucesso e acreditaria que está escrevendo softwares robustos, quando, na verdade, não está fazendo nada do tipo.

    
por 24.04.2017 / 16:19
fonte
96
  1. Porque C tem um tipo void e Java foi projetado para seguir muitas das convenções da família da linguagem C.
  2. Existem muitas funções que você não deseja que retornem um valor. O que você vai fazer com "um genérico Success type" de qualquer maneira? Na verdade, os valores de retorno para indicar o sucesso são ainda menos importantes em Java do que em C, porque o Java possui exceções para indicar falhas e o C não.
por 24.04.2017 / 16:14
fonte
65

A razão original porque a linguagem tem um void é porque, como em C , os criadores da linguagem não queriam complicar desnecessariamente a sintaxe da linguagem com procedimento e função s como Pascal fez.

Esse foi o motivo original.

Suas sugestões:

returning a status flag

Isso é um não-não. Nós não usamos flags de status. Se algo der errado, denunciá-lo por meio de exceções.

the object being invoked

O estilo fluente de invocações é um desenvolvimento recente. Muitos dos programadores que estão muito felizes usando fluentemente hoje e rolando os olhos, se alguma vez tiverem que usar uma interface que não suporta, nem nasceram quando o Java foi criado.

returning null

Isso forçaria você a declarar um método como algo que retorna, quando na verdade não está retornando nada, então seria muito confuso para alguém que está olhando para uma interface tentando descobrir o que ela faz. As pessoas inventariam inevitavelmente alguma classe de outra forma inútil que significa "nenhum valor de retorno", de modo que todas as funções que não têm nada a devolver possam retornar uma referência nula a essa classe. Isso seria desajeitado. Felizmente, existe uma solução para isso, chama-se void . E essa é a resposta para sua pergunta.

    
por 24.04.2017 / 21:07
fonte
20

Alguns métodos, como System.out.println , não retornam nada útil, mas são chamados apenas para esse efeito colateral. void é um indicador útil para o compilador e para o leitor de código que nenhum valor útil é retornado.

Retornar null em vez de void significa que você obteria apenas um NullPointerException no momento em que usar esse valor para qualquer coisa. Então você troca um erro de tempo de compilação por um erro de runtime que é muito pior. Além disso, você teria que definir o tipo de retorno como Object , o que seria enganoso e confuso. (E encadeamento ainda não funcionaria.)

Os códigos de status geralmente são usados para indicar condições de erro, mas o Java tem exceções para esse propósito.

A devolução de this não é possível a partir de métodos estáticos.

Retornar um objeto genérico Success não teria um objetivo útil.

    
por 24.04.2017 / 21:48
fonte
11

Uma razão é que pode ser enganoso para retornar alguma coisa diferente de, digamos, null . Exemplo:

O que deve Arrays.sort(a) retornar?

Se você argumentar que a deve ser retornado para que a chamada possa ser encadeada (o que parece ser sua resposta a julgar pela sua pergunta), não será mais claro se o valor de retorno é uma cópia do objeto original ou do próprio objeto original. Ambos são possíveis. E sim, você poderia colocá-lo na documentação, mas é suficientemente ambíguo que você não deva criar a ambiguidade em primeiro lugar.

Por outro lado, se você argumentar que null deve ser retornado, isso levanta a questão de quais informações o valor de retorno está possivelmente fornecendo ao chamador e por que o programador deve ser forçado a escrever return null quando transmite sem informação.

E se você retornar algo totalmente absurdo (como o comprimento de a ), então isso fará com que o valor de retorno seja realmente confuso - pense em quanto mais confuso é dizer int len = Arrays.sort(a) em vez de int len = A.length !

    
por 26.04.2017 / 01:46
fonte
7

Retornar um boolean que é sempre igual a true que você sugere, não é apenas inútil (o valor de retorno não contém informações), mas na verdade seria enganador. Na maioria das vezes, é melhor usar tipos de retorno que contêm apenas o máximo de informações disponíveis. É por isso que em Java você tem boolean para true / false em vez de retornar int com 4 bilhões possíveis valores. Da mesma forma, retornar um boolean com dois valores possíveis, onde há apenas um valor possível ("sucesso genérico"), seria enganoso.

Isso também adicionaria 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 tornar void um tipo real, como Unit do Scala. Isso resolveria alguns problemas, como o tratamento de genéricos.

    
por 24.04.2017 / 19:12
fonte
4

Java é uma linguagem relativamente antiga. E em 1995 (quando foi criado) e logo depois os programadores ficaram muito preocupados com a quantidade de tempo que um processo assumia o controle do processador, bem como o consumo de memória. Retornar vazio elimina alguns ciclos de clock e um pouco de consumo de memória de uma chamada de função porque você não teria que colocar o valor de retorno na pilha, e você não teria que removê-lo posteriormente.

O código eficiente não lhe 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 do que retornar um valor de sucesso.

    
por 24.04.2017 / 19:12
fonte
2

Eu li argumentos que sugerem que a segunda opção (return this ) deve ser a abordagem em vez de void . Esta é uma boa idéia, mas a abordagem estilo construtor não era popular no momento em que o Java foi criado. Se fosse tão popular na época como é agora, essa poderia ter sido a abordagem adotada. Retornar null é uma ideia muito ruim da IMO. Eu gostaria que null não estivesse sequer na língua.

O problema agora é que, se um método retornar uma instância de seu próprio tipo, não está claro se esse é um novo objeto ou o mesmo. Muitas vezes não importa (ou não deveria), mas outras vezes isso importa. Eu suponho que a linguagem poderia ser alterada para retornar implicitamente this em métodos vazios. O único problema que posso pensar com isso no momento é que, se o método foi 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 importa com esses tipos de mudanças agora. Como isso interage com herança / interfaces precisaria de alguma consideração, mas permitiria que APIs antigas sem um estilo de construtor fossem facilmente chamadas como se fossem.

    
por 24.04.2017 / 18:36
fonte
2

Outro aspecto:

O Java é uma linguagem estática com recursos bastante rígidos. Isso significa que muitas coisas que seriam bastante abertas ou dinâmicas em outras linguagens (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 "what for" é bem claro: ele permite que o compilador detecte um lote de erros, o que geralmente é um bom recurso para qualquer idioma. Em segundo lugar, torna relativamente fácil raciocinar sobre o idioma. Por exemplo, é relativamente fácil criar correção formal em (subconjuntos) da linguagem Java; como comparação, isso seria virtualmente 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 OOP imperativa estática do mundo real com strong foco no tratamento de erros de tempo de compilação), essas coisas são realmente muito elegantes e poderosas. Eles se aproximam de linguagens teóricas (científicas) que são intencionalmente feitas apenas para explorar algumas dessas questões do que qualquer outra linguagem do mundo real antes (na época, lembre-se).

Ter um tipo void estrito é uma mensagem clara: esse método não retorna nada, ponto final. É o que é. Substituí-lo pela imposição para sempre retornar algo levaria a um comportamento muito mais dinâmico (como em Ruby, onde cada def tem um valor de retorno explícito ou implícito, sempre), o que seria ruim para provabilidade e raciocínio ; ou ao inchaço massivo usando algum outro mecanismo aqui.

(E NB, Ruby (por exemplo) lida com isso de forma diferente, e sua solução ainda é exatamente aceitável como Java, porque tem uma filosofia completamente diferente. Por exemplo, ele gera provabilidade e razoabilidade completamente fora da janela ao colocar um grande foco na expressividade extremamente alta da linguagem.

    
por 25.04.2017 / 16:50
fonte