Como modificar a adição de inteiros em java?

Sep 03 2020

Então, basicamente, eu estava fazendo uma pesquisa porque estava curioso para ver se isso poderia ser feito e encontrei este código:

import java.lang.reflect.Field;


public class Main {
    public static void main(String[] args) throws Exception {
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field c = cache.getDeclaredField("cache");
        c.setAccessible(true);
        Integer[] array = (Integer[]) c.get(cache);
        array[132] = array[133];

      int  n = 2+2;
      System.out.println(n);
      System.out.printf("%d",2 + 2);
    }
}

Eu estava simplesmente curioso para saber por que a instrução printf agora retornaria 5, mas imprimir o número inteiro n ainda me daria 4.

Respostas

3 Sweeper Sep 04 2020 at 00:47

Java armazena em cache 256 Integerobjetos que representam os números de -128 a 127. Quando um inté encaixotado em um Integer, se seu valor estiver entre -128 e 127, o Integerobjeto do cache será usado. ( Saiba mais aqui ). Como a linguagem faz isso são detalhes de implementação. Em sua versão do Java, ele armazena esse cache em uma classe interna em Integer, em um Integer[]campo chamado cache. Em alguma outra versão do Java, isso pode mudar, então seu código pode falhar.

O que a primeira parte do seu código está fazendo é obter o cache inteiro e definir o índice 132 para ser o mesmo que o índice 133. Uma vez que este array começa em -128, o índice 132 corresponderia a onde 4 é, e o índice 133 seria onde 5 é. Isso significa que você substituiu 4 no cache por 5.

O argumento para printf, 2 + 2primeiro fica avaliada a 4. Em seguida, ele fica em caixa a um Integer. Isso ocorre porque printfsó aceita um Objectcomo seu segundo parâmetro. Como 4 está entre -128 e 127, o cache é usado e o índice 132 do array é acessado, porque é onde o Integer4 estaria, se você não tivesse modificado o array. Mas você modificou o array, então ele obteve 5.

Por outro lado, printlnainda imprime 4 porque printlntem uma sobrecarga que aceita int, então nenhum boxing ocorre ali.

A propósito, você não está modificando a "adição de inteiro", você está apenas modificando o "box de inteiro".