Este artigo explora conceitos fundamentais em Java, incluindo o comportamento de enums, representação de números em binário e o processamento de operações com strings e variáveis.
Comportamento de Enums
Ao comparar instâncias de enumeração em Java, observamos:
s == tretornafalse, indicando quesetreferenciam objetos de enumeração distintos.s.getClass().isPrimitive()retornafalse, pois os tipos enum não são tipos primitivos.s == uretornatrue. Isso ocorre porqueufoi obtido usandoSize.valueOf("SMALL"), que retorna a instância de enumeração correspondente ao nome fornecido.for(Size value:Size.values())itera e exibe todas as instâncias disponíveis do enum.
Em resumo, as instâncias de enumeração são únicas; cada valor de enum é uma instância exclusiva da classe enum. Tipos enum são tipos de referência, não tipos primitivos. Métodos como valueOf() e values() facilitam a obtenção de instâncias e de todas as instâncias de um enum, respectivamente.
Representação Numérica Binária
Java utiliza a representação em complemento de dois para números inteiros:
- Código Original (Sign-Magnitude): O bit mais à esquerda indica o sinal (0 para positivo, 1 para negativo), e os bits restantes representam o valor absoluto.
- Código Inverso (One's Complement): Para números negativos, o bit de sinal permanece o mesmo, e todos os outros bits são invertidos (0 vira 1, 1 vira 0).
- Complemento de Dois (Two's Complement): Para números negativos, é o resultado do código inverso somado a 1.
O código a seguir demonstra a representação binária de números positivos e negativos em Java:
public class BinaryRepresentation {
public static void main(String[] args) {
int positiveNumber = 5;
int negativeNumber = -5;
System.out.println("Representação Binária:");
System.out.println("Positivo (" + positiveNumber + "): " + Integer.toBinaryString(positiveNumber));
System.out.println("Negativo (" + negativeNumber + "): " + Integer.toBinaryString(negativeNumber));
// Exibindo representações conceituais (não diretamente acessíveis em Java)
System.out.println("\nConceitos de Representação:");
// Código Original (simplificado para demonstração)
System.out.println("Código Original (Negativo): 1" + Integer.toBinaryString(Math.abs(negativeNumber)).substring(1));
// Código Inverso (simplificado para demonstração)
String invertedBits = Integer.toBinaryString(Math.abs(negativeNumber)).substring(1).replace('0', '#').replace('1', '0').replace('#', '1');
System.out.println("Código Inverso (Negativo): 1" + invertedBits);
// Complemento de Dois (como Java armazena)
System.out.println("Complemento de Dois (Negativo): " + Integer.toBinaryString(negativeNumber));
}
}
Atenção às Operações de String e Concatenação
A ordem das operações e os tipos de dados envolvidos em uma instrução println podem alterar o resultado:
- Quando uma string é o primeiro operando em uma expressão com o operador
+, o Java realiza concatenação de strings. Isso significa que os operandos subsequentes, mesmo que numéricos, são convertidos em strings e anexados. - Se a adição numérica ocorrer antes da concatenação, o resultado numérico será obtido primeiro e, em seguida, concatenado com a string.
Considere os seguintes exemplos:
public class StringConcatenation {
public static void main(String[] args) {
String x = "100";
String y = "200";
System.out.println("Exemplo 1: " + x + y); // Concatenação de strings
System.out.println("Exemplo 2: " + (Integer.parseInt(x) + Integer.parseInt(y))); // Adição numérica seguida de conversão para string
System.out.println(Integer.parseInt(x) + Integer.parseInt(y) + ": Resultado"); // Adição numérica seguida de conversão para string
}
}
A saída esperada é:
Exemplo 1: 100200
Exemplo 2: 300
300: Resultado
No primeiro caso, "100" + "200" resulta na string "100200". Nos casos seguintes, as strings "100" e "200" são primeiro convertidas para inteiros, somadas resultando em 300, e então convertidas de volta para string para exibição.
Escopo de Variáveis e Sombra (Shadowing)
O "Variable Shadwoing" ocorre quando uma variável local (ou um parâmetro de método) tem o mesmo nome de uma variável de instância ou de classe. Nesse cenário, a variável local tem precedência dentro de seu escopo, "escondendo" a variável de escopo mais amplo.
public class VariableShadowing {
int instanceVar = 10; // Variável de instância
public void methodWithLocalVar() {
int instanceVar = 20; // Variável local com o mesmo nome
System.out.println("Valor da variável local em methodWithLocalVar: " + instanceVar); // Acessa a variável local (20)
}
public void methodAccessingInstanceVar() {
System.out.println("Valor da variável de instância em methodAccessingInstanceVar: " + this.instanceVar); // Acessa explicitamente a variável de instância (10)
}
public static void main(String[] args) {
VariableShadowing example = new VariableShadowing();
example.methodWithLocalVar(); // Saída: 20
example.methodAccessingInstanceVar(); // Saída: 10
}
}
No método methodWithLocalVar, a variável local instanceVar de valor 20 é utilizada. Já no método methodAccessingInstanceVar, a palavra-chave this é usada para referenciar explicitamente a variável de instância instanceVar, que tem o valor 10.
Tamanhos e Faixas de Tipos Primitivos Numéricos
Java define tipos primitivos numéricos com tamanhos e faixas de valores específicos:
byte: 8 bits, faixa de -128 a 127.short: 16 bits, faixa de -32.768 a 32.767.int: 32 bits, faixa de -2.147.483.648 a 2.147.483.647.long: 64 bits, faixa de -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807.float: 32 bits, precisão simples, aproximadamente de -3.4e38 a 3.4e38.double: 64 bits, precisão dupla, aproximadamente de -1.7e308 a 1.7e308.