import java.util.*;
import java.lang.*;

class Main
{
	public static void main (String[] args) throws java.lang.Exception
	{
		System.out.println("Hello...");
		
		//////////////////////////////////////////////////////////
		
		Something st1 = new Something(1,2.3);
		Something st2 = new Something(4,5.6);
		
		st1.print();
		st2.print();
		
		//st1.swap(st2);
		swap(st1, st2);
		
		st1.print();
		st2.print();
		
		//////////////////////////////////////////////////////////
		
		Integer i1 = 5;
		Integer i2 = 10;
		
		System.out.println("i1: " + i1 + "\r\ni2: " + i2 + "\r\n");
		
		// when we do swap intensive-code:
		
		Variable<Integer> v1 = new Variable(i1);
		Variable<Integer> v2 = new Variable(i2);
		
		swap(v1, v2);
		swap(v1, v2);
		swap(v1, v2);
		// ...
		
		i1 = v1.getValue();
		i2 = v2.getValue();
		
		// end of swap-intensive-code: "unbox" the Veriable<T>s into the original Ts
		
		System.out.println("i1: " + i1 + "\r\ni2: " + i2 + "\r\n");
	}
	
	private static <T extends Swappable> void swap(T a, T b)
	{
		a.swap(b);
	}
}

interface Swappable<T extends Swappable>
{
	public void swap(T other);
}

class Something implements Swappable<Something>
{
	private int i;
	private double d;
	
	public Something(int _i, double _d)
	{
		this.i = _i;
		this.d = _d;
	}
	
	public void print()
	{
		System.out.println("i: " + i + "\r\nd: " + d + "\r\n");
	}
	
	public void swap(Something other)
	{
		int _i = other.i;
		double _d = other.d;
		
		other.i = this.i;
		other.d = this.d;
		
		this.i = _i;
		this.d = _d;
	}
}

class Variable<T> implements Swappable<Variable<T>>
{
	T value;
	
	public Variable(T _value)
	{
		this.value = _value;
	} // Variable(T)
	
	public void setValue(T newvalue)
	{
		this.value = newvalue;
	} // setValue(T)
	
	public T getValue()
	{
		return this.value;
	} // getValue()
	
	public void swap(Variable<T> other)
	{
		T tmp = this.value;
		this.setValue(other.getValue());
		other.setValue(tmp);
	} // swap(Variable<T> other)
} // class Variable<T>