Q:

Java changes reference but not the object itself?

Please see the following code:
public static void main(String[] args)
{
    Test t1 = new Test();
    t1.i = 1;
    Test t0 = t1;
    Test t2 = new Test();
    t2.i = 2;
    t0 = t2; 
    System.out.println(t1.i); //prints 1, I thought it would print 2
}

Is there any way to change t1 object after I got it from somewhere else by simple assignment without accessing t1 directly? (i.e. t1 = t0)

A:

Here is an illustration of your program and what it does. Each state of the system is shown separated by a dashed line.
Note what happens when you do t0 = t1. You assumed that this means that from now on, t0 and t1 are synonyms - whenever you use one, the other is affected. But in fact, t0 and t1 are simply two references to the same object.
Making a new assignment to t0 simply detached it from the "blue" object and re-attached it to the "violet" object.
As long as t0 and t1 were both pointing at the same object, any changes you make in the content of their pointed object (such as t0.i = 5) would be seen by the other reference, because they both refer to the same object. But as soon as you assign something else to t0, it loses its connection to t1. After you do that, changing it will be reflected in t2, which points to the same, "violet" object, not in t1 which still points to the old, "blue" one.
So:

If you assign a new value to the reference - it no longer points to the same object as before, and any previous "double referencing" is lost.
If you assign a new value to the content of the reference, it will be reflected in all reference variables that look at the same object.

