Spróbujmy od tej strony:
JVM (wirtualny maszyna Javy) ma dwa wydzielone obszary pamięci - heap i stack.
Zmienna:
Type name; // deklaracja zmiennej o typie Type
Typy prymitywne, czyli te pisane z małej (boolean, char, int, long, float, double) są trzymane w stack'u.
przykładowo:
public int foo(){
int i = 1; // w stack'u tworzona jest zmienna, której wartością będzie 1
// do smth
return -1; // po wykonaniu tej instrukcji zmienna i jest usuwana z stack'a
}
Obiekty - w zależności od widzimisię kompilatora, trafiają do heap'a lub stack'u. Zazwyczaj do tego pierwszego, do drugiego mogą trafić tylko w sytuacjach szczególnych (jak maszyna uzna, że tak będzie szybciej i prościej). I tak:
public MyPojo foo(){
MyPojo pojo = new MyPojo(); // w heap'ie tworzony jest obiekt
return null; // w tym miejscu nie musi on zostać usunięty, jedynie zostanie oznaczony jako "do usunięcia"
}
Obiekt pojo zostanie usunięty z pamięci dopiero w momencie, w którym GC przeskanuje heap w celu usunięcia zbędnych danych.
Referencja to taki szczególny typ obiektu, którego zadaniem jest przechowywać zależność pomiędzy zmienną, a obszarem w pamięci, pod którą kryje się obiekt. Czyli:
MyPojo pojo; // tworzona jest zmienna
pojo = new MyPojo(); // w tym miejscu tworzony jest obiekt MyPojo, i referencja do obiektu. Nastpnie do zmiennej "pojo" przypisana jest referencja do utworzonego obiektu
Wrappery to szczególne typy obiektów, które "opakowują" typy prymitywne. Typy są pisane wielką literą, np. Integer, String, Double itp. Tak jak już tutaj było napisane, można je tworzyć poprzez operator "new":
Integer myInt = new Integer(1); // tworzony jest nowy obiekt Integer o wartości 1, do tej zmiennej przypisywana jest referencja do tego obiektu.
Jak wiemy można obiekty typu Integer tworzyć bezpośrednio przez operator przypisania. Jest to pewna metoda mająca na celu zwiększenie wydajności i de facto jest to po prostu łatwiejszy sposób na wywołanie Integer.valueOf, tj.
Integer int1 = 1;
Integer int2 = Integer.valueOf(1);
Integer int3 = new Integer(1);
Integer int4 = 1;
System.out.println(int1 == int2); // true, zmienne int1 i int2 posiadają referencje wskazujące na ten sam obiekt w pamięci
System.out.println(int1 == int3); // false
System.out.println(int1 == int4); // true
Ot, takie usprawnienie dla developerów.