Vamos lá.
Wrapper não tem nada de mágico; é só um objeto que encapsula (“embrulha”) um tipo primitivo.
Quando você usa “new”, sempre é criado um novo objeto - sem dó nem piedade. Sempre.
Só que quando você usa wrappers, o Java já deixa prontos 256 objetos (de -128 a +127) já “pré-alocados” para poder usar com o método valueOf. Isso vale para Integer, Short, Byte e Long. (Para Boolean ele deixa pronto Boolean.TRUE e Boolean.FALSE; e para Character ele deixa pronto de (char) 0 até (char) 127.)
Se você usar valueOf, ou então ocorrer o autoboxing (que é uma forma disfarçada de chamar valueOf), ele primeiro vê se o valor que você está pedindo está entre -128 e +127. Se estiver, ele lhe retorna um desses objetos já pré-alocados. Se não estiver, ele simplesmente chama “new”, mesmo que você já tenha usado o valor antes.
Exemplo:
Long L = Long.valueOf (12345); // usa new porque o valor é grande
Long M = Long.valueOf (12345); // usa new porque o valor é grande
System.out.println (L == M); // imprime false
L = Long.valueOf (42); // pega o pré-alocado porque o valor é pequeno
M = Long.valueOf (42); // pega o pré-alocado porque o valor é pequeno
System.out.println (L == M); // imprime true
Atenção - isso não deve cair em sua certificação. É só um detalhe de implementação.
Para comparar corretamente dois wrappers, use equals, que compara os valores, não as referências dos objetos