Pergunta

Depois de postagem esta questão e leitura de que um percebi que é muito importante saber se um método é suposto return null, ou se esta é considerada uma condição de erro e uma exceção deve ser acionada. Há também uma boa discussão quando a ou lance exceção .

Eu estou escrevendo um método e eu já sei se eu quiser retornar nulo ou lançar uma exceção, qual é a melhor maneira de expressar a minha decisão, em outras palavras, para documentar meu contrato?

Algumas maneiras que eu posso pensar de:

  • Escreva-o nas especificações / documentação (Será que alguém lê-lo?)
  • Faça-o parte do nome do método (como eu sugeri aqui )
  • assumir que cada método que lança uma exceção não return null, e cada um que faz 'e não' jogar pode return null.

Eu estou falando principalmente sobre java, mas pode aplicar-se a outras línguas, também: Porque é que existe uma maneira formal para expressar se as exceções serão lançados (as palavras-chave throws) mas não há maneira formal para expressar se nula pode ser devolvido ?

Por que não há algo como isso:

public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}

Resumo e Conclusão

Existem muitas maneiras de expressar o contrato:

  • Se suas sustentações IDE-lo (como IntelliJ), é melhor usar uma anotação como @NotNull porque é visível para o programador e pode ser usado para a verificação de tempo de compilação automatizada. Há um plugin para Eclipse para adicionar suporte para estes, mas isso não aconteceu trabalho para mim.
  • Se estes não são uma opção, Tipos de uso personalizados como Option<T> ou NotNull<T>, que adicionar clareza e pelo menos verificação de tempo de execução.
  • Em qualquer maneira, documentando o contrato no JavaDoc nunca é demais e às vezes até ajuda.
  • Usando nomes de métodos para documentar o nulidade do valor de retorno não foi proposto por ninguém além de mim, e embora possa ser muito detalhado und nem sempre útil, eu ainda acredito que às vezes tem suas vantagens, também.
Foi útil?

Solução

Um bom acompanhamento pergunta. Considero null um valor verdadeiramente especial, e se um método pode retornar null ele deve claramente documento no Javadoc quando isso acontece (@return some value ..., or null if ...). Quando a codificação Estou defensiva, e assumir um método pode retornar null menos que eu estou convencido de que não pode (por exemplo, porque o Javadoc disse isso.)

As pessoas perceberam que este é um problema, e uma proposta de solução é usar anotações para declarar a intenção de uma forma que pode ser verificado automaticamente. Consulte JSR 305: Anotações para Software Detecção de Defeitos , JSR 308: Anotações sobre tipos Java e o JetBrain Nullable How-To .

O seu exemplo pode parecer com isto, e recusado pelo IDE, as ferramentas do compilador ou outra análise de código.

@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}

Outras dicas

De fato: em nosso quadro temos uma 'não-null' tipo de ponteiro, que pode ser retornado para indicar que o método sempre retornará um valor

.

Eu vejo três opções:

  1. espera para suporte ao idioma para expressá-lo (por exemplo, o C #?! coisa )
  2. Orientação uso Aspect para construir suas próprias extensões de linguagem para expressá-lo
  3. usar um tipo personalizado para expressá-lo
  4. (mas baseia-se na cooperação desenvolvedor) usa um esquema de nomes para indicar que

Para Java, pode-se usar a descrição Javadoc de um método para documentar o significado do valor retornado, incluindo se ele pode ser nulo. Como já foi mencionado, anotações também podem fornecer assistência aqui.

Por outro lado, eu admito que eu não vejo nulo como algo a ser temido. Há situações em que "ninguém em casa" é uma condição significativa (embora a técnica objeto nulo também tem valor real aqui).

É certamente verdade que tentar uma invocação de método em um valor nulo fará com que uma exceção. Mas assim que a tentativa de dividir por zero. Isso não significa que precisamos para ir em uma campanha para eliminar zeros! Significa apenas que nós precisamos entender o contrato em um método e fazer a coisa certa com os valores que ele retorna.

Você teve uma olhada Spec # ?

Você pode escrever seu próprio anotação (Java) ou atributo (C #) para indicar que o valor de retorno pode ser nulo. Nada irá verificar automaticamente (embora .NET 4.0 terá contratos de código para esse tipo de coisa), mas seria, pelo menos agir como documentação.

Há algum suporte para um @Nullable e @NotNull anotação no IntelliJ IDEA . Há também alguma conversa sobre a adição dessas anotações (ou um recurso semelhante) para Java 7. Infelizmente eu não sei o quão longe que tem ou se ele ainda está no caminho certo em tudo.

Talvez você poderia definir uma classe genérica com o nome "NotNull", de modo que o seu método pode ser como:

public NotNull<Object> methodWhichCannotReturnNull(int i) throws Exception
{
   // the following would lead to a run-time error thown by the
   // NotNull constructor, if it's constructed with a null value
   return new NotNull<Object>(null);
}

Este ainda é um run-time (não um tempo de compilação) cheque, mas:

  • É jogado na implementação do método (não é uma falha no código de chamada)
  • É auto-documentado (o chamador sabe que ele está nos preparando NotNull<T> como um tipo de retorno)

Em todos os custos, evitar depender dos JavaDocs. As pessoas só lê-los se a assinatura não parece trivial e auto-explicativo (que é ruim para começar), e estes que realmente se preocupam em lê-los são menos propensos a cometer um erro com os nulos, uma vez que estão actualmente a ser mais cuidadoso .

Se você estiver usando Java 5 +, você pode usar uma anotação de costume, por exemplo, @MayReturnNull

Atualizar

Todos codificação filosofia de lado (retornando null, usando exceções, afirmações, yada yada), espero que as respostas acima sua pergunta. Além de primitivas que têm valores padrão, tipos complexos pode ou não pode ser nulo, e suas necessidades de código para lidar com ele.

De um modo geral, eu diria que um valor nulo de retorno é contra o contrato da API por padrão. É quase sempre possível projetar seu código de tal forma que um valor nulo não é retornado de suas APIs durante o "normal" fluxo de execução. (Por exemplo, foo.contains cheque (obj) em vez chamando foo.get (obj) e tendo um ramo separado para null. Ou, use o Null objeto padrão .

Se você não pode projetar sua API de tal maneira, eu o faria claramente documento quando e por que um nulo poderia ser jogado - em menos no Javadoc, e possivelmente também usando um @annotation costume tais como várias das outras respostas sugeriram.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top