Obiekty są przekazywane przez referencję, to prawda, ale same referencje przekazywane są już przez wartość.
Twoje rozwiązanie jest tak naprawdę w pierwszym poście tego wątku. Trzeba stworzyć klasę Wskaźnik, która jako taka będzie przechowywała referencję jakiegoś typu, np. Object dla wskaźników dowolnego typu.
Są tylko dwa poważne problemy takiego podejścia:
Po pierwsze "wskaźnik" taki zupełnie nie posiada kontroli typów. Możnaby spróbować zabawić się w typy ogólne. Ale ponieważ te w Javie są zaimplementowane z zacieraniem, więc użyteczność wskaźników typowanych nie dość że byłaby bardzo niska, to katastrofalnie zaciemniałaby kod. A to z takiego powodu, że trzeba by było dodać jeszcze jeden poziom dziedziczenia/implementacji.
W związku z tym ten rodzaj wskaźnika jest jeszcze bardziej niebezpieczny od wskaźników w C/C++, które mają jednak kontrolę typów.
Drugi to efektywność i rozmiar w pamięci... 16 bajtów, to jednak trochę dużo.
No i na koniec to co poniżej, to bardziej referencja niż wskaźnik. Aby zrobić z tego wskaźnik trzebaby pobawić się refleksją dla wykrywania że wskaźnik został zainicjowany kolekcją lub tablicą tak aby można było przypisać referencję pierwszego obiektu i stworzyć metody do arytmetyki wskaźnikami w ramach takiej struktury. Wtedy dopiero możnaby to nazwać inteligentnym wskaźnikiem z dynamicznym sprawdzaniem typów.
package Olamagato;
public class Pointer
{
public Pointer() {} //wskaźnik pusty
public Pointer(Object o) { ref = o; } //wskaźnik z inicjacją
//przypisanie wskazania
public Pointer set(Object o)
{
ref = o;
return this; //set może zostać użyte w wyrażeniach
}
//wyłuskanie wskazania
public Object get() { return ref; }
//zamiana wskaźników, brak odpowiednika w C/C++
public Pointer swap(Pointer swapped)
{
Object tmp = ref;
ref = swapped.get();
swapped.set(tmp);
return this;
}
private Object ref;
}
package Kandydaci;
import Olamagato.Pointer;
class A
{
public Pointer id;
}
class B
{
public Pointer id;
}
class C
{
public Pointer id;
}
public class TestPointer
{
public static void main(String[] args)
{
int t[] = { 10, 20, 30 };
A a = new A(); B b = new B(); C c = new C();
a.id = new Pointer(); //przypisanie referencji
b.id = a.id; //przepisanie wskaźnika
c.id = b.id; //przepisanie wskaźnika
a.id.set(t[0]);
System.out.printf("a = %d\nb = %d\nc = %d\n",
a.id.get(), b.id.get(), c.id.get()); //wyłuskanie wskaźników
b.id.set(t[1]);
System.out.printf("a = %d\nb = %d\nc = %d\n",
a.id.get(), b.id.get(), c.id.get()); //wyłuskanie wskaźników
c.id.set(t[2]);
System.out.printf("a = %d\nb = %d\nc = %d\n",
a.id.get(), b.id.get(), c.id.get()); //wyłuskanie wskaźników
a.id.set(40);
System.out.printf("a = %d\nb = %d\nc = %d\n",
a.id.get(), b.id.get(), c.id.get()); //wyłuskanie wskaźników
}
}
/*
run:
a = 10
b = 10
c = 10
a = 20
b = 20
c = 20
a = 30
b = 30
c = 30
a = 40
b = 40
c = 40
*/
}
ps. Oczywiście zadziałał w tym przykładzie autoboxing, dzięki któremu każdy int z tablicy został opakowany przez Integer, do którego pobrana została referencja.