Por que os designers de Java não criaram versões estáticas dos métodos de manipulação de string na java.lang.String
classe? Os métodos a seguir são os que me refiro, mas a pergunta também pode ser estendida a outros métodos não estáticos da classe.
concat(String) substring(int, int)
replace(char, char) toLowerCase()
replace(CharSequence, CharSequence) toLowerCase(Locale)
replaceAll(String, String) toString()
replaceFirst(String, String) toUpperCase()
split(String) toUpperCase(Locale)
split(String, int) trim()
substring(int)
Ter apenas versões não estáticas desses métodos força a verificação nula explícita em qualquer lugar em que esse método precise ser chamado. Por exemplo, simplesmente chamar example = example.trim()
levaria a NullPointerException if String example = null
. Portanto, o programador deve fazer a seguinte verificação nula padrão:
if (example != null)
example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);
Eu imagino que teria sido muito mais conveniente se String
tivesse versões estáticas desses métodos (talvez até exclusivamente ), que usariam a string de entrada como o primeiro argumento:
example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);
Isso levaria a um código mais limpo, escrito por programadores, que cuidaria automaticamente de casos nulos simplesmente retornando nulo, em vez de forçar os programadores a lidar explicitamente com casos nulos. O retorno de null faz sentido para mim, pois a manipulação de uma string nula deve resultar em uma string nula , não em erro.
Por que os designers de Java não pensaram nisso quando criaram a String
classe em Java 1 ou Java 2, ou mesmo adicionaram essa funcionalidade em uma versão Java posterior?
fonte
null
é um estado excepcional e deve ser tratado explicitamente.Maybe<T>
tipo, eu acho?string name = employee?.personalData?.name
. Apenas como um atalho para todos esses repetitivosif (employee != null)
. Pergunta relacionada ao SO: stackoverflow.com/questions/1196031/…Respostas:
Bem, essa é a sua opinião. Outros podem argumentar que as operações String em um objeto nulo, que não contém uma String, não fazem sentido e, portanto, devem lançar uma Exceção
Por que "designers de Java" fizeram ou não algo é difícil de responder.
Já existem bibliotecas por aí que podem executar operações de String com segurança nula, por exemplo, StringUtils do Apache Commons. Você pode usar essas bibliotecas ou similares, se precisar delas.
Adição com base nos seus comentários
Lendo os comentários, parece que o verdadeiro problema que você enfrenta é que você precisa verificar
null
todo o seu código. Isso pode ser um indicador de um mau design do programa sem contratos claramente definidos entre interfaces. Você pode querer ler Evitando instruções "! = Null" em Java?fonte
Optional
- code.google.com/p/guava-libraries/wiki/…Na IMO, toda a abordagem "se arg é nulo retorna nulo" para escrever métodos desnecessariamente aumenta a complexidade ciclomática do seu programa.
As bibliotecas Java anteriores usavam a abordagem de retorno nulo, mas os caras do JDK sempre se protegiam contra o nulo, com exceções.
Com o tempo, acho que a última abordagem saiu como a clara vencedora.
Por quê? Como os campos nulos quebram muitos princípios. Você simplesmente não pode tratá-los como membros de uma classe polimórfica. Isso significa que você sempre deve codificar casos especiais para nulo e, portanto, sua complexidade ciclomática aumenta quando você assume que as coisas podem ser nulas.
Para resolver seus problemas, considere usar o padrão de objeto nulo em vez de confiar em campos nulos.
fonte
String
não é polimórfico, não? E como você usa o padrão de objeto nulo para um tipo já existente como String?int
padrão é zero em vez denull
. Conceitualmente, deve ser possível ter umstring
tipo cujo valor padrão seja uma string vazia em vez denull
[esse tipo pode ser semanticamente oString
queint
é necessárioInteger
]. O fato de um não-vaziostring
conter internamente uma referência a um objeto de heap seria um detalhe de implementação; não há razão para que ele não se comporte semanticamente como um primitivo.Sem dizer que esse é o motivo, mas, exceto para toString, todos esses métodos são facilmente encapsulados em uma classe auxiliar estática, enquanto o inverso não é verdadeiro.
Ou seja, se você deseja Stings.toUpper (entrada de string), o código para isso é fácil de escrever, mas se você quer instance.toUpper e tudo o que você tem é String.toUpper, bem, isso é impossível ... a menos que eles introduzam métodos de extensão, o que provavelmente nem foi considerado na época.
fonte
String.format
(estático), mas não pode"something %s".format(id)
.Em java, essa string é um objeto. Essa é uma escolha de design.
As referências a objetos podem ser nulas e nulas se não houver um objeto atribuído a ela. Se você chamar esse objeto, uma NullPointerException será lançada. Isso é oo-comportamento padrão.
Os designers de Java escolheram ter strings como objeto e ter esses métodos lançando exceções de ponteiros nulos é o que você obtém se quiser que os strings sejam objetos.
Eles provavelmente pensaram sobre isso e optaram por incorporar oo-comportamento.
fonte
String.format
. (Mesmo em C #, a propósito). Portanto, se essa é uma opção de design, não pode vir apenas do fato de que as strings são objetos e não são aplicadas de forma consistente.Strings
classe de utilitário, como aArrays
classe de utilitário ( embora eu entenda que ele foi criado por pura necessidade, porque as matrizes são uma espécie de cruzamento estranho entre primitivos e objetos: ) ) .. desde que fizesse parte do Java padrão e não exigisse dependências.