CodeGym /Blogue Java /Random-PT /Classe Java.lang.Integer
John Squirrels
Nível 41
San Francisco

Classe Java.lang.Integer

Publicado no grupo Random-PT
Os tipos de dados Java podem ser divididos condicionalmente em dois blocos: primitivo e referência (classes). Existem vários tipos de dados primitivos em Java, como inteiros ( byte , short , int , long ), números de ponto flutuante ( float , double ), tipo de dados lógicos ( boolean ) e tipo de dados de caractere ( char ). Você provavelmente já sabe que cada tipo de dados primitivo possui sua própria classe wrapper. Um tipo de dados de referência que "envolve" ou transforma seu irmão primitivo em um objeto Java. Integer é uma classe wrapper para seu irmão primitivo chamado int. Inteiro em inglês significa um número inteiro. Eles podem ser positivos, negativos ou 0. Infelizmente, Inteiro em Java não significa nenhum número inteiro. Inteiro em java é um número inteiro que cabe em 32 bits. Se você quiser um número maior, poderá usar números Java Long . Eles têm 64 bits à sua disposição. Se você tiver o azar de precisar de um número ainda maior, o Java o ajudará com BigInteger .

Trabalhando com inteiro

Como uma classe wrapper, Integer fornece vários métodos para trabalhar com int , bem como vários métodos para converter int em String e String em int . A classe possui dois construtores:
  • public Integer(int i) , onde i é um valor primitivo para inicializar. Este cria um objeto Integer que é inicializado com o valor int .

  • public Integer(String s) lança NumberFormatException . Aqui s é uma representação em string do valor int . Este construtor cria um objeto Integer que foi inicializado com o valor int fornecido pela representação de string .

Criação de objeto inteiro

Existem diferentes opções de criação de objetos inteiros . Um dos mais comumente usados ​​é o mais fácil. Aqui está um exemplo:
Integer myInteger = 5;
A inicialização da variável Integer neste caso é semelhante à inicialização da variável int primitiva . A propósito, você pode inicializar uma variável Integer com o valor de um int . Aqui está um exemplo:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
A saída aqui é:
5
Na verdade, aqui podemos observar a embalagem automática. Também podemos criar um objeto Integer como qualquer outro objeto usando um construtor e uma nova palavra-chave:
Integer myInteger = new Integer(5);
Você pode fazer com a variável Integer o mesmo que com int (adicionar, subtrair, multiplicar, dividir, incrementar, decrementar). Porém, é importante lembrar que Inteiro é um tipo de dados de referência e uma variável desse tipo pode ser nula. Neste caso, é melhor abster-se de tais operações.
Integer myInteger1  = null;
Integer myInteger2 = myInteger1 + 5;
Aqui teremos uma exceção:
Exceção no thread "main" java.lang.NullPointerException"

Constantes de classe inteira

A classe Integer fornece várias constantes e métodos para trabalhar com números inteiros. Aqui estão eles:
  • SIZE significa o número de bits no sistema numérico de dois dígitos ocupados pelo tipo int

  • BYTES é o número de bytes no sistema numérico de dois dígitos ocupados pelo tipo int

  • MAX_VALUE é o valor máximo que o tipo int pode conter

  • MIN_VALUE é o valor mínimo que o tipo int pode conter

  • TYPE retorna um objeto do tipo Class do tipo int

Métodos mais úteis da classe inteira

Agora vamos dar uma olhada nos métodos mais usados ​​da classe Integer . O mais popular deles, presumo, são métodos para converter um número de String , ou vice-versa.
  • static int parseInt(String s) este método converte String em int . Se a conversão não for possível, NumberFormatException será lançada.

  • static int parseInt(String s, int radix) este método também converte o parâmetro s em um int . O parâmetro radix indica que o sistema numérico foi originalmente escrito.

Além de parseInt , há também um método valueOf muito semelhante em diversas variações. No entanto, o resultado de valueOf será Integer e parseInt será int .
  • static Integer valueOf(int i) retorna um inteiro cujo valor é i ;

  • static Integer valueOf(String s) funciona como parseInt(String s) , mas o resultado será Integer , não int ;

  • static Integer valueOf(String s, int radix) funciona da mesma forma que parseInt(String s, int radix) , mas o resultado é um Integer , não um int .

Existe algum problema com a classe Integer? Ah sim, existe…

Portanto, existem dois tipos de números inteiros (que cabem em 32 bits) em Java: int e Integer . Para entender as especificidades de cada um deles precisamos saber o seguinte sobre o modelo de memória JVM: tudo que você declara é armazenado ou em Stack Memory (JVM Stack específico para cada Thread), ou Heap Space. Tipos primitivos ( int , long , float , boolean , double , char , byte , etc) são armazenados na memória Stack. Todos os objetos e arrays são armazenados no Heap Space. As referências a esses objetos e arrays necessários para os métodos são armazenadas em Stack. Então. Por que nos importamos? Bem, veja bem, Stack é menor que Heap (um contra), mas é muito mais rápido alocar valores em Stack do que em Heap (um profissional). Vamos começar com um tipo primitivo int . Ocupa exatamente 32 bits. Isso é 32/8 = 4 bytes. Porque é um tipo primitivo. Agora, vamos considerar Integer . É um objeto, com sobrecarga e alinhamentos extras. Eu usei uma biblioteca jol para medir seu tamanho:
public static void main(String[] args) {
 	System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
e acabou ocupando 16 bytes:
Internos do objeto java.lang.Integer: OFF SZ TIPO DESCRIÇÃO VALOR 0 8 (cabeçalho do objeto: marca) 0x000000748c90e301 (hash: 0x748c90e3; idade: 0) 8 4 (cabeçalho do objeto: classe) 0x000492a0 12 4 int Integer.value 1 Tamanho da instância: 16 bytes
O que?! Isso é 4 vezes mais memória! Mas não vamos parar por aí. Como desenvolvedores Java normalmente não paramos de usar um único número inteiro. O que realmente queremos é usar muitos deles. Como em uma sequência. Por exemplo, em uma matriz. Ou uma lista. As matrizes são armazenadas no Heap, assim como as listas. Portanto, a alocação deve levar aproximadamente o mesmo tempo. Certo? Mas e se precisarmos alocar mais memória? Vamos verificar quanto espaço ocupa um array de 1000 valores int primitivos:
public static void main(String[] args) {
    	int[] array = new int[1000];
    	for (int i = 0; i < 1000; i++) array[i] = i;                System.out.println(ClassLayout.parseInstance(array).toPrintable());
}
E o resultado são 4.016 bytes:
OFF SZ TIPO DESCRIÇÃO VALOR 0 8 (cabeçalho do objeto: marca) 0x0000000000000001 (não polarizável; idade: 0) 8 4 (cabeçalho do objeto: classe) 0x00006c38 12 4 (comprimento da matriz) 1000 12 4 (lacuna de alinhamento/preenchimento) 16 4000 int [I.<elements> N/A Tamanho da instância: 4.016 bytes Perdas de espaço: 4 bytes internos + 0 bytes externos = 4 bytes no total
OK, isso faz sentido, considerando que um único int ocupa 4 bytes. Que tal um ArrayList<Integer> de 1000 Integers ? Vamos dar uma olhada:
public static void main(String[] args) {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
      System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
E o resultado são 2.0040 bytes (novamente, 4 vezes mais!):
java.util.ArrayList@66d3c617d pegada: COUNT AVG SUM DESCRIÇÃO 1 4016 4016 [Ljava.lang.Object; 1000 16 16000 java.lang.Integer 1 24 24 java.util.ArrayList 1002 20040 (total)
Portanto, ArrayList<Integer> ocupa 4 vezes mais espaço de memória. Isso não é bom. Mesmo assim, as listas são mais fáceis porque podemos adicionar e excluir elementos! Oh Java… Por que você precisa encaixotar tudo?! Mas, estou esquecendo, Java é ótimo, e sua grandeza reside na abundância de bibliotecas de código aberto que podemos usar! Trove4j é um deles. Possui TIntArrayList que internamente possui dados int[] . Vamos medir seu tamanho:
public static void main(String[] args) {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
E o resultado é 4.040 bytes (quase o mesmo que apenas int[] !):
gnu.trove.list.array.TIntArrayList@7440e464d pegada: COUNT AVG SUM DESCRIÇÃO 1 4016 4016 [I 1 24 24 gnu.trove.list.array.TIntArrayList 2 4040 (total)
Então, no final, podemos ter o melhor dos dois mundos! Listas de inteiros que ocupam 4 vezes menos espaço. E isso não envolve instâncias inteiras . Somente ints . Nós, desenvolvedores Java, realmente nos preocupamos com a memória… Mas também nos preocupamos com o desempenho. Há uma maravilhosa biblioteca de microbenchmarking com um nome modesto jmh que nos permite medir o desempenho do código. Primeiro vamos comparar o desempenho do cálculo de uma soma de dois inteiros aleatórios, em caixa ou não: A configuração para jmh é a seguinte:
benchmark {
	configurations {
    	main {
        	warmups = 5 // number of warmup iterations
        	iterations = 50 // number of iterations
        	iterationTime = 500 // time in seconds per iteration
        	iterationTimeUnit = "ns" // time unit for iterationTime
Os benchmarks:
private static final Random random = new Random();

@Benchmark
public int testPrimitiveIntegersSum() {
	int a = random.nextInt();
	int b = random.nextInt();
	return a + b;
}

@Benchmark
public Integer testBoxedIntegersSum() {
	Integer a = random.nextInt();
	Integer b = random.nextInt();
	return a + b;
}
Os resultados:
principal: test.SampleJavaBenchmark.testBoxedIntegersSum 5693337,344 ±(99,9%) 1198774,178 ops/s [Média] (min, avg, max) = (1092314,989, 5693337,344, 12001683,428), stdev = 24215 83,144 IC (99,9%): [4494563,166, 6892111,522] (assume distribuição normal) principal: test.SampleJavaBenchmark.testPrimitiveIntegersSum 15295010,959 ± (99,9%) 2555447,456 ops/s [Média] (min, avg, max) = (4560097,059, 15295010,959, 24283809,447), st desv = 5162130,283 IC (99,9%): [12739563.502, 17850458.415] (assume distribuição normal)
Portanto, em média, a alocação e a soma de inteiros primitivos são duas vezes mais rápidas que a de inteiros em caixa. Agora, vamos comparar o desempenho de criação e cálculo de soma de coleções (ou arrays de 1000 ints de inteiros):
@Benchmark
public int testPrimitiveArray() {
	int[] array = new int[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
11933.545 ops/s [Average]


@Benchmark
public int testBoxesArray() {
	Integer[] array = new Integer[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
2733.312 ops/s [Average]


@Benchmark
public int testList() {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int x : list) sum += x;
	return sum;
}
2086.379 ops/s [Average]


@Benchmark
public int testTroveIntList() {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int i = 0; i < 1000; i++) sum += list.get(i);
	return sum;
}
5727.979 ops/s [Average]
Os resultados: o array de primitivos é mais de 4 vezes mais rápido que o array de valores em caixa ( Integer s); quase seis vezes mais rápido que ArrayList de valores em caixa ( Integer s); e duas vezes mais rápido que um TIntArrayList (que na verdade decora uma matriz de entradas primitivas). Portanto, se você precisa de uma estrutura de dados para armazenar uma coleção de valores inteiros e seu tamanho não vai mudar, use um int[] ; se o tamanho for mudar - você pode querer usar a biblioteca tove4j com TIntArrayList . E aqui chega o final do meu ensaio, onde explico os contras de usar o tipo Integer . Existem alguns métodos estáticos interessantes de Integer , sobre os quais devo falar antes de terminar. public static Integer getInteger(String nm, int val) não faz o que se poderia pensar, mas recupera um valor inteiro de uma propriedade do sistema. Val é o padrão caso esta propriedade não esteja definida. public static String toBinaryString(int i) retorna uma String com uma representação binária de um número. Existem métodos para recuperação de representações baseadas em 16 ( toHexString ) e baseadas em 8 ( toOctalString ). Existe um método para analisar uma String em um int . Mesmo que a string seja uma representação baseada em raiz diferente de 10. Aqui estão alguns exemplos: Integer.parseInt("-FF", 16) retorna -255 Integer.parseInt("+42", 10) retorna 42 Integer.parseInt("1100110", 2) retorna 102
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION