Eu vejo que Java tem booleano (classe) vs booleano (primitivo). Da mesma forma, há um número inteiro (classe) vs int (primitivo). Qual é a melhor prática sobre quando usar a versão primitiva versus a classe? Eu basicamente sempre deveria estar usando a versão da classe, a menos que eu tenha um motivo específico (de desempenho?) Para não? Qual é a maneira mais comum e aceita de usar cada um?
54
Respostas:
No item 5, do Java efetivo, Joshua Bloch diz
Um bom uso para classes é ao usá-las como tipos genéricos (incluindo classes de coleção, como listas e mapas) ou quando você deseja transformá-las em outro tipo sem conversão implícita (por exemplo,
Integer
classe possui métodosdoubleValue()
oubyteValue()
.Edit: A razão de Joshua Bloch é:
fonte
A prática padrão é seguir as primitivas, a menos que você esteja lidando com genéricos (certifique-se de estar ciente de caixas automáticas e unboxing !).
Existem várias boas razões para seguir a convenção:
1. Você evita erros simples:
Existem alguns casos sutis e não intuitivos, que geralmente envolvem iniciantes. Até mesmo codificadores experientes escorregam e cometem esses erros algumas vezes (espero que isso seja seguido por palavrões quando eles depurarem o código e encontrarem o erro!).
O erro mais comum é usar em
a == b
vez dea.equals(b)
. As pessoas estão acostumadas a fazer uso dea == b
primitivas, portanto isso é fácil quando você está usando os wrappers Object.2. Legibilidade:
Considere os dois exemplos a seguir. A maioria das pessoas diria que o segundo é mais legível.
3. Desempenho:
O fato é que é mais lento usar os wrappers Object para primitivas do que apenas usar as primitivas. Você está adicionando o custo da instanciação de objetos, chamadas de métodos etc. às coisas que usa em todo o lugar .
A citação de Knuth "... digamos cerca de 97% do tempo: a otimização prematura é a raiz de todo mal" não se aplica aqui. Ele estava falando sobre otimizações que tornam o código (ou sistema) mais complicado - se você concorda com o ponto 2, essa é uma otimização que torna o código menos complicado!
4. É a convenção:
Se você fizer escolhas estilísticas diferentes para 99% dos outros programadores Java, existem duas desvantagens:
Normalmente eu listaria alguns contrapontos, mas honestamente não consigo pensar em nenhuma boa razão para não ir à convenção aqui!
fonte
==
. Objetos devem ser comparados comequals()
.equals()
... você fornece uma solução alternativa para que comparar objetos com==
produza os resultados esperados.equals()
ao segundo trecho de código e mudei meu voto.Normalmente eu vou com os primitivos. No entanto, uma peculiaridade de usar classes como
Integer
eBoolean
é a possibilidade de atribuirnull
a essas variáveis. Claro, isso significa que você tem que fazernull
verificações o tempo todo, mas ainda melhor para obter um NullPointerException do que ter erros de lógica, devido ao uso de algunsint
ouboolean
variável que não foi inicializado corretamente.Obviamente, desde o Java 8, você pode (e provavelmente deveria) ir um passo além e, em vez de, por exemplo,
Integer
usarOptional<Integer>
para variáveis que podem ou não ter um valor.Além disso, apresenta a possibilidade de usar
null
para atribuir a essas variáveis um valor " desconhecido " ou " curinga ". Isso pode ser útil em algumas situações, por exemplo, na lógica ternária . Ou você pode verificar se um determinado objeto corresponde a algum modelo; nesse caso, você pode usarnull
para aquelas variáveis no modelo que podem ter qualquer valor no objeto.fonte
null
como padrão. Pelo contrário: seria melhor não "inicializar" a variável. Definir qualquer valor padrão, mesmonull
, desliga o compilador ... mas também evita a detecção de falta de atribuição útil em todos os caminhos de código. Assim, um erro que o compilador poderia ter detectado desliza para o tempo de execução.0.0
, ou-1
, ouInteger.MAX_VALUE
, ouFalse
, mas, no final, você não sabe se esse é o valor padrão ou um valor real que foi atribuído a essa variável. Nos casos em que isso é importante, ter umnull
valor pode ser mais claro.null
vêm com uma série de problemas, incluindo paranóia nula.) Em uma função, uma variável que pode realmente não ser inicializada no ponto de uso normalmente indica casos não descobertos. (A análise de atribuição definida é simplista, portanto, são possíveis falsos positivos. Mas muitas vezes você pode resolvê-los simplificando a lógica.)Nas palavras dos leigos:
Você usa os wrappers quando precisa adicionar itens às coleções.
As coleções não podem conter primitivas.
fonte
O Java apresenta a autoboxing como m3th0dman apontou. Pense no nível mais baixo possível e você verá que a autoboxing (entrada ou saída) de um valor primitivo implicará ciclos de relógio gastos em algumas tarefas que você não precisa se estiver trabalhando com tipos de dados nativos em seu aplicativo.
Como regra geral, você deve tentar usar tipos de dados nativos sempre que possível.
fonte