class Cup {}
class Mug extends Cup {}
class BigMug extends Mug {}
class BigRedMug extends BigMug {}

	//\\//\\//\\//\\//\\//
	//\\ class declaration
	//\\//\\//\\//\\//\\//
	class Set1<E> {
	    E e;
//	    void putc(Cup e)    { this.e = e; }		// incompatible types
//	    void putm(Mug e)    { this.e = e; }		// incompatible types
//	    void putb(BigMug e) { this.e = e; }		// incompatible types
	    void pute(E e)      { this.e = e; }
	    Object geto() { return e; }
//	    Cup    getc() { return e; }			// incompatible types
//	    Mug    getm() { return e; }			// incompatible types
//	    BigMug getb() { return e; }			// incompatible types
	    E      gete() { return e; }
	}
	class Set2<E extends Mug> {
	    E e;
//	    void putc(Cup e)    { this.e = e; }		// incompatible types
//	    void putm(Mug e)    { this.e = e; }		// incompatible types
//	    void putb(BigMug e) { this.e = e; }		// incompatible types
	    void pute(E e)      { this.e = e; }
	    Object geto() { return e; }
	    Cup    getc() { return e; }
	    Mug    getm() { return e; }
//	    BigMug getb() { return e; }			// incompatible types
	    E      gete() { return e; }
	}
//	class Set1<E extends Mug> {}	// duplicate class
//	class Set1<E, F> {}		// duplicate class
//	class Set3<E super Mug> {}	// type parameter cannot be "super"

class GenericsTest {
    Object    obj;
    Cup       cup;
    Mug       mug;
    BigMug    big;
    BigRedMug red;

    //\\//\\//\\//\\//\\//\\//
    //\\ variable declaration
    //\\//\\//\\//\\//\\//\\//
    Set1<Cup>               c1;
    Set1<Mug>               m1;
    Set1<BigMug>            b1;
    Set1<?>                 x1;
    Set1<? extends Cup>    uc1;
    Set1<? extends Mug>    um1;
    Set1<? extends BigMug> ub1;
    Set1<? super Cup>      lc1;
    Set1<? super Mug>      lm1;
    Set1<? super BigMug>   lb1;

//  Set2<Cup>               c2;	// type parameter Cup is not within its bound
    Set2<Mug>               m2;
    Set2<BigMug>            b2;
    Set2<?>                 x2;
    Set2<? extends Cup>    uc2;
    Set2<? extends Mug>    um2;
    Set2<? extends BigMug> ub2;
//  Set2<? super Cup>      lc2;	// type parameter ? super Cup is not within its bound
    Set2<? super Mug>      lm2;
    Set2<? super BigMug>   lb2;
    
	/************************************************************
					upper	lower
					bound	bound
	 Set1<Cup>               c1;	Cup	Cup
	 Set1<Mug>               m1;	Mug	Mug
	 Set1<BigMug>            b1;	BigMug	BigMug
	 Set1<?>                 x1;	Object	--
	 Set1<? extends Cup>    uc1;	Cup	--
	 Set1<? extends Mug>    um1;	Mug	--
	 Set1<? extends BigMug> ub1;	BigMug	--
	 Set1<? super Cup>      lc1;	Object	Cup
	 Set1<? super Mug>      lm1;	Object	Mug
	 Set1<? super BigMug>   lb1;	Object	BigMug
	
	 Set2<Cup>               c2;	Mug	Cup	un-reasonable
	 Set2<Mug>               m2;	Mug	Mug
	 Set2<BigMug>            b2;	BigMug	BigMug
	 Set2<?>                 x2;	Mug	--	same as um2
	 Set2<? extends Cup>    uc2;	Mug	--	same as um2
	 Set2<? extends Mug>    um2;	Mug	--
	 Set2<? extends BigMug> ub2;	BigMug	--
	 Set2<? super Cup>      lc2;	Mug	Cup	un-reasonable
	 Set2<? super Mug>      lm2;	Mug	Mug	same as m2
	 Set2<? super BigMug>   lb2;	Mug	BigMug
	 ************************************************************/

    public static void main(String[] s) {
    }

    void method() {

	//\\//\\//\\//\\//\\//
	//\\ instance creation
	//\\//\\//\\//\\//\\//
	new Set1<Cup>();
	new Set1<Mug>();
	new Set1<BigMug>();
//	new Set2<Cup>();	// type parameter Cup is not within its bound
	new Set2<Mug>();
	new Set2<BigMug>();

	//\\//\\//\\//\\//\\//\\//\\//\\//
	//\\ object to variable assignment
	//\\//\\//\\//\\//\\//\\//\\//\\//
	   c1=new Set1<Cup>();  /* c1=new Set1<Mug>();*//* c1=new Set1<BigMug>();*/	// incompatible types
	/* m1=new Set1<Cup>();*/   m1=new Set1<Mug>();  /* m1=new Set1<BigMug>();*/
	/* b1=new Set1<Cup>();*//* b1=new Set1<Mug>();*/   b1=new Set1<BigMug>();
	   x1=new Set1<Cup>();     x1=new Set1<Mug>();     x1=new Set1<BigMug>();
	  uc1=new Set1<Cup>();    uc1=new Set1<Mug>();    uc1=new Set1<BigMug>();
	/*um1=new Set1<Cup>();*/  um1=new Set1<Mug>();    um1=new Set1<BigMug>();
	/*ub1=new Set1<Cup>();    ub1=new Set1<Mug>();*/  ub1=new Set1<BigMug>();
	  lc1=new Set1<Cup>();  /*lc1=new Set1<Mug>();*//*lc1=new Set1<BigMug>();*/
	  lm1=new Set1<Cup>();    lm1=new Set1<Mug>();  /*lm1=new Set1<BigMug>();*/
	  lb1=new Set1<Cup>();    lb1=new Set1<Mug>();    lb1=new Set1<BigMug>();

	   m2=new Set2<Mug>();  /* m2=new Set2<BigMug>();*/	// incompatible types
	/* b2=new Set2<Mug>();*/   b2=new Set2<BigMug>();
	   x2=new Set2<Mug>();     x2=new Set2<BigMug>();
	  uc2=new Set2<Mug>();    uc2=new Set2<BigMug>();
	  um2=new Set2<Mug>();    um2=new Set2<BigMug>();
	/*ub2=new Set2<Mug>();*/  ub2=new Set2<BigMug>();
	  lm2=new Set2<Mug>();  /*lm2=new Set2<BigMug>();*/
	  lb2=new Set2<Mug>();    lb2=new Set2<BigMug>();

	//\\//\\//\\//\\//\\//\\//\\//\\//\\//
	//\\ variable to variable assignment
	//\\//\\//\\//\\//\\//\\//\\//\\//\\//
	   c1=c1;  /* c1=m1;*//* c1=b1;*//* c1=x1;*//* c1=uc1;*//* c1=um1;*//* c1=ub1;*//* c1=lc1;*//* c1=lm1;*//* c1=lb1;*/
	/* m1=c1;*/   m1=m1;  /* m1=b1;*//* m1=x1;*//* m1=uc1;*//* m1=um1;*//* m1=ub1;*//* m1=lc1;*//* m1=lm1;*//* m1=lb1;*/
	/* b1=c1;*//* b1=m1;*/   b1=b1;  /* b1=x1;*//* b1=uc1;*//* b1=um1;*//* b1=ub1;*//* b1=lc1;*//* b1=lm1;*//* b1=lb1;*/
	   x1=c1;     x1=m1;     x1=b1;     x1=x1;     x1=uc1;     x1=um1;     x1=ub1;     x1=lc1;     x1=lm1;     x1=lb1;
	  uc1=c1;    uc1=m1;    uc1=b1;  /*uc1=x1;*/  uc1=uc1;    uc1=um1;    uc1=ub1;  /*uc1=lc1;*//*uc1=lm1;*//*uc1=lb1;*/
	/*um1=c1;*/  um1=m1;    um1=b1;  /*um1=x1;*//*um1=uc1;*/  um1=um1;    um1=ub1;  /*um1=lc1;*//*um1=lm1;*//*um1=lb1;*/
	/*ub1=c1;*//*ub1=m1;*/  ub1=b1;  /*ub1=x1;*//*ub1=uc1;*//*ub1=um1;*/  ub1=ub1;  /*ub1=lc1;*//*ub1=lm1;*//*ub1=lb1;*/
	  lc1=c1;  /*lc1=m1;*//*lc1=b1;*//*lc1=x1;*//*lc1=uc1;*//*lc1=um1;*//*lc1=ub1;*/  lc1=lc1;  /*lc1=lm1;*//*lc1=lb1;*/
	  lm1=c1;    lm1=m1;  /*lm1=b1;*//*lm1=x1;*//*lm1=uc1;*//*lm1=um1;*//*lm1=ub1;*/  lm1=lc1;    lm1=lm1;  /*lm1=lb1;*/
	  lb1=c1;    lb1=m1;    lb1=b1;  /*lb1=x1;*//*lb1=uc1;*//*lb1=um1;*//*lb1=ub1;*/  lb1=lc1;    lb1=lm1;    lb1=lb1;

	   m2=m2;  /* m2=b2;*//* m2=x2;*//* m2=uc2;*//* m2=um2;*//* m2=ub2;*/   m2=lm2;  /* m2=lb2;*/
	/* b2=m2;*/   b2=b2;  /* b2=x2;*//* b2=uc2;*//* b2=um2;*//* b2=ub2;*//* b2=lm2;*//* b2=lb2;*/
	   x2=m2;     x2=b2;     x2=x2;     x2=uc2;     x2=um2;     x2=ub2;     x2=lm2;     x2=lb2;
	  uc2=m2;    uc2=b2;    uc2=x2;    uc2=uc2;    uc2=um2;    uc2=ub2;    uc2=lm2;    uc2=lb2;
	  um2=m2;    um2=b2;    um2=x2;    um2=uc2;    um2=um2;    um2=ub2;    um2=lm2;    um2=lb2;
	/*ub2=m2;*/  ub2=b2;  /*ub2=x2;*//*ub2=uc2;*//*ub2=um2;*/  ub2=ub2;  /*ub2=lm2;*//*ub2=lb2;*/
	  lm2=m2;  /*lm2=b2;*//*lm2=x2;*//*lm2=uc2;*//*lm2=um2;*//*lm2=ub2;*/  lm2=lm2;  /*lm2=lb2;*/
	  lb2=m2;    lb2=b2;  /*lb2=x2;*//*lb2=uc2;*//*lb2=um2;*//*lb2=ub2;*/  lb2=lm2;    lb2=lb2;
	  
	    /*******************************************************************
	     assignable if
	     the bounds of left-hand-side contains the bounds of right-hand-side
	     *******************************************************************/

	//\\//\\//\\//\\//
	//\\ put element
	//\\//\\//\\//\\//
	   c1.e=red;    c1.e=big;    c1.e=mug;    c1.e=cup; // c1.e=obj;	// incompatible types
	   m1.e=red;    m1.e=big;    m1.e=mug; // m1.e=cup;    m1.e=obj;
	   b1.e=red;    b1.e=big; // b1.e=mug;    b1.e=cup;    b1.e=obj;
	// x1.e=red;    x1.e=big;    x1.e=mug;    x1.e=cup;    x1.e=obj;
	//uc1.e=red;   uc1.e=big;   uc1.e=mug;   uc1.e=cup;   uc1.e=obj;
	//um1.e=red;   um1.e=big;   um1.e=mug;   um1.e=cup;   um1.e=obj;
	//ub1.e=red;   ub1.e=big;   ub1.e=mug;   ub1.e=cup;   ub1.e=obj;
	  lc1.e=red;   lc1.e=big;   lc1.e=mug;   lc1.e=cup; //lc1.e=obj;
	  lm1.e=red;   lm1.e=big;   lm1.e=mug; //lm1.e=cup;   lm1.e=obj;
	  lb1.e=red;   lb1.e=big; //lb1.e=mug;   lb1.e=cup;   lb1.e=obj;

	   m2.e=red;    m2.e=big;    m2.e=mug; // m2.e=cup;    m2.e=obj;	// incompatible types
	   b2.e=red;    b2.e=big; // b2.e=mug;    b2.e=cup;    b2.e=obj;
	// x2.e=red;    x2.e=big;    x2.e=mug;    x2.e=cup;    x2.e=obj;
	//uc2.e=red;   uc2.e=big;   uc2.e=mug;   uc2.e=cup;   uc2.e=obj;
	//um2.e=red;   um2.e=big;   um2.e=mug;   um2.e=cup;   um2.e=obj;
	//ub2.e=red;   ub2.e=big;   ub2.e=mug;   ub2.e=cup;   ub2.e=obj;
	  lm2.e=red;   lm2.e=big;   lm2.e=mug; //lm2.e=cup;   lm2.e=obj;
	  lb2.e=red;   lb2.e=big; //lb2.e=mug;   lb2.e=cup;   lb2.e=obj;
	  
	    /******************************************************
	     using the lower bound, then applying polymorphism rule
	     ******************************************************/

	//\\//\\//\\//
	//\\ putter
	//\\//\\//\\//
	// 與 put element 相同
	   c1.pute(big);    c1.pute(mug);    c1.pute(cup);
	   m1.pute(big);    m1.pute(mug); // m1.pute(cup);	// pute(...) in Set1<...> cannot be applied to (...)
	   b1.pute(big); // b1.pute(mug);    b1.pute(cup);
	// x1.pute(big);    x1.pute(mug);    x1.pute(cup);
	//uc1.pute(big);   uc1.pute(mug);   uc1.pute(cup);
	//um1.pute(big);   um1.pute(mug);   um1.pute(cup);
	//ub1.pute(big);   ub1.pute(mug);   ub1.pute(cup);
	  lc1.pute(big);   lc1.pute(mug);   lc1.pute(cup);
	  lm1.pute(big);   lm1.pute(mug); //lm1.pute(cup);
	  lb1.pute(big); //lb1.pute(mug);   lb1.pute(cup);

	   m2.pute(big);    m2.pute(mug); // m2.pute(cup);
	   b2.pute(big); // b2.pute(mug);    b2.pute(cup);
	// x2.pute(big);    x2.pute(mug);    x2.pute(cup);
	//uc2.pute(big);   uc2.pute(mug);   uc2.pute(cup);
	//um2.pute(big);   um2.pute(mug);   um2.pute(cup);
	//ub2.pute(big);   ub2.pute(mug);   ub2.pute(cup);
	  lm2.pute(big);   lm2.pute(mug); //lm2.pute(cup);	// pute(Mug) in Set2<Mug> cannot be applied to (Cup) 特別
	  lb2.pute(big); //lb2.pute(mug);   lb2.pute(cup);

	//\\//\\//\\//\\//
	//\\ get element
	//\\//\\//\\//\\//
	  obj= c1.e;   cup= c1.e; //mug= c1.e;   big= c1.e;   red= c1.e;	// incompatible types
	  obj= m1.e;   cup= m1.e;   mug= m1.e; //big= m1.e;   red= m1.e;
	  obj= b1.e;   cup= b1.e;   mug= b1.e;   big= b1.e; //red= b1.e;
	  obj= x1.e; //cup= x1.e;   mug= x1.e;   big= x1.e;   red= x1.e;
	  obj=uc1.e;   cup=uc1.e; //mug=uc1.e;   big=uc1.e;   red=uc1.e;
	  obj=um1.e;   cup=um1.e;   mug=um1.e; //big=um1.e;   red=um1.e;
	  obj=ub1.e;   cup=ub1.e;   mug=ub1.e;   big=ub1.e; //red=ub1.e;
	  obj=lc1.e; //cup=lc1.e;   mug=lc1.e;   big=lc1.e;   red=lc1.e;
	  obj=lm1.e; //cup=lm1.e;   mug=lm1.e;   big=lm1.e;   red=lm1.e;
	  obj=lb1.e; //cup=lb1.e;   mug=lb1.e;   big=lb1.e;   red=lb1.e;

	  obj= m2.e;   cup= m2.e;   mug= m2.e; //big= m2.e;   red= m2.e;	// incompatible types
	  obj= b2.e;   cup= b2.e;   mug= b2.e;   big= b2.e; //red= b2.e;
	  obj= x2.e;   cup= x2.e;   mug= x2.e; //big= x2.e;   red= x2.e;
	  obj=uc2.e;   cup=uc2.e;   mug=uc2.e; //big=uc2.e;   red=uc2.e;
	  obj=um2.e;   cup=um2.e;   mug=um2.e; //big=um2.e;   red=um2.e;
	  obj=ub2.e;   cup=ub2.e;   mug=ub2.e;   big=ub2.e; //red=ub2.e;
	  obj=lm2.e;   cup=lm2.e;   mug=lm2.e; //big=lm2.e;   red=lm2.e;
	  obj=lb2.e;   cup=lb2.e;   mug=lb2.e; //big=lb2.e;   red=lb2.e;
	    
	    /******************************************************
	     using the upper bound, then applying polymorphism rule
	     ******************************************************/

	//\\//\\//\\//
	//\\ getter
	//\\//\\//\\//
	  cup= c1.gete(); //mug= c1.gete();   big= c1.gete();	// incompatible types
	  cup= m1.gete();   mug= m1.gete(); //big= m1.gete();
	  cup= b1.gete();   mug= b1.gete();   big= b1.gete();
	//cup= x1.gete();   mug= x1.gete();   big= x1.gete();
	  cup=uc1.gete(); //mug=uc1.gete();   big=uc1.gete();
	  cup=um1.gete();   mug=um1.gete(); //big=um1.gete();
	  cup=ub1.gete();   mug=ub1.gete();   big=ub1.gete();
	//cup=lc1.gete();   mug=lc1.gete();   big=lc1.gete();
	//cup=lm1.gete();   mug=lm1.gete();   big=lm1.gete();
	//cup=lb1.gete();   mug=lb1.gete();   big=lb1.gete();

	  cup= m2.gete();   mug= m2.gete(); //big= m2.gete();	// incompatible types
	  cup= b2.gete();   mug= b2.gete();   big= b2.gete();
	  cup= x2.gete();   mug= x2.gete(); //big= x2.gete();
	  cup=uc2.gete();   mug=uc2.gete(); //big=uc2.gete();
	  cup=um2.gete();   mug=um2.gete(); //big=um2.gete();
	  cup=ub2.gete();   mug=ub2.gete();   big=ub2.gete();
	  cup=lm2.gete();   mug=lm2.gete(); //big=lm2.gete();
	  cup=lb2.gete();   mug=lb2.gete(); //big=lb2.gete();

	  cup= m2.getc(); //mug= m2.getc();   big= m2.getc();	// incompatible types
	  cup= b2.getc(); //mug= b2.getc();   big= b2.getc();
	  cup= x2.getc(); //mug= x2.getc();   big= x2.getc();
	  cup=uc2.getc(); //mug=uc2.getc();   big=uc2.getc();
	  cup=um2.getc(); //mug=um2.getc();   big=um2.getc();
	  cup=ub2.getc(); //mug=ub2.getc();   big=ub2.getc();
	  cup=lm2.getc(); //mug=lm2.getc();   big=lm2.getc();
	  cup=lb2.getc(); //mug=lb2.getc();   big=lb2.getc();

	  cup= m2.getm();   mug= m2.getm(); //big= m2.getm();	// incompatible types
	  cup= b2.getm();   mug= b2.getm(); //big= b2.getm();
	  cup= x2.getm();   mug= x2.getm(); //big= x2.getm();
	  cup=uc2.getm();   mug=uc2.getm(); //big=uc2.getm();
	  cup=um2.getm();   mug=um2.getm(); //big=um2.getm();
	  cup=ub2.getm();   mug=ub2.getm(); //big=ub2.getm();
	  cup=lm2.getm();   mug=lm2.getm(); //big=lm2.getm();
	  cup=lb2.getm();   mug=lb2.getm(); //big=lb2.getm();
    }
}
