//==================================================================================================
// To allow a class to be generic for any data type... 
//       use <anySymbol> (example <T> or <E> or <anyType> after the name of the class
// When instantiating an object of that class...
//    1) Identify the actual datatype you will be using the class within <....>
//    2) Place an empty <> after the name of the class 
//    see line 41
//==================================================================================================
class genericsClass <T>
{
    T elem;                                         //define an element of any type

    genericsClass(T input)                          //constructor that takes any data type
    {
        this.elem = input;
    }
    void print()                                    //regular instance method                                    
    {
        System.out.println(elem + " ");
    }
    static <T> void print2(T input)                 //method that takes any data type
    {
        System.out.println(input + " ");
    }
    static <T> T print3(T input)                    //method that takes and returns any data type
    {
        System.out.println(input + " ");
        return(input);
    }
}
//==================================================================================================
// When instantiating an object of a generic class...
//    1) Identify the actual datatype you will be using the class within <....>
//    2) Place an empty <> after the name of the class 
//    see line 41
//==================================================================================================
public class genericsClassTest
{
    public static void main(String[] args)
    {
        genericsClass<Integer> obj1 = new genericsClass<>(1234);            //instantiate generic objects 
        obj1.print();                                                       //call method
        genericsClass<Double>  obj2 = new genericsClass<>(123.45);
        obj2.print();
        genericsClass<String>  obj3 = new genericsClass<>("Hello World");
        obj3.print();

        System.out.println();
 
        Integer i = obj1.elem;                              
        genericsClass.print2(i);                            //call method and pass it Integer type
        Double  d = obj2.elem;                              
        genericsClass.print2(d);                            //call same method and pass it Double type
         
        String s;                               
        s = genericsClass.print3(obj3.elem);                //pass and receive generic type
    }
}