public class aliases_methods {
    public static void main(String args[]) {

	Data a1 = new Data(1);
	Data a2 = new Data(2);
	Data a3 = new Data(3);

	System.out.println("BEFORE METHOD CALL");
	System.out.println("test_a1: " + a1.k);
	System.out.println("test_a2: " + a2.k);
	System.out.println("test_a3: " + a3.k);

	// Ouput:
	// BEFORE METHOD CALL
	// test_a1: 1
	// test_a2: 2
	// test_a3: 3

	test(a1,a2,a3);

	System.out.println("AFTER METHOD CALL");
	System.out.println("test_a1: " + a1.k);
	System.out.println("test_a2: " + a2.k);
	System.out.println("test_a3: " + a3.k);

	// Output:
	// AFTER METHOD CALL
	// test_a1: 1
	// test_a2: 2
	// test_a3: 3

	// Why don't the objects change?
	//
	// Yes, the formal parameters in test(___) become 
	// aliases of the actual parameters a1, a2, and a3 from main(___).
	// And yes, the formal parameters in test now point to other objects.
	// But, when the test(___) method finishes, the local variables,
	// which include the formal parameters, dies. And the actual
	// parameters in main(___) still refer to the original objects.

    }

    public static void test(Data a1, Data a2, Data a3) {
	// make a2 an alias for a1
	a2 = a1;

	// make a3 an alias for b
	Data b = new Data(4);
	a3 = b;

	System.out.println("DURING METHOD CALL");
	System.out.println("test_a1: " + a1.k);
	System.out.println("test_a2: " + a2.k);
	System.out.println("test_a3: " + a3.k);

	// Output:	
	// AFTER METHOD CALL
	// test_a1: 1
	// test_a2: 2
	// test_a3: 3

    }

}

class Data {
    int k;
    Data(int k) {
	this.k = k;
    }
}
