C:\Common\_Project_Source_\Towson\ProgrammingSamples\src\Generics\GenericClass.java
  1 /*
  2  * This file contains several generefied classes and simple demonstration of the
  3  * usage of those classes. While examing the code, it is important to remember
  4  * that -- in Java -- it is the Job of the COMPILER to check and enforce type
  5  * saftey.  At runtime, it is assumed that the compiler (and hence, the programmer)
  6  * has already resolved any potential "type saftey" issues.  Type-saftey is important
  7  * because many common program failures are the result of attempting to perform
  8  * an unsupported operation on a piece of data... usually as a result of many
  9  * different programmers working together on the same large application.  Static
 10  * typing guarentees that the data-type you expect is the data type you get!
 11  *
 12  */
 13 package Generics;
 14 
 15 /**
 16  * @author Adam J. Conover <adam@adamconover.com>
 17  */
 18 public class GenericClass {
 19 
 20     /**
 21      * This class is just used to test/demonstrate the classes below.
 22      * @param args the command line arguments
 23      */
 24     public static void main(String[] args) {
 25         Fuji f1 = new Fuji(335);  
 26         Orange f2 = new Orange(275);
 27         Sunkist f3 = new Sunkist();
 28 
 29         MySimpleContainer<Apple> appleContainer = new MySimpleContainer<Apple>(f1);
 30         MyComparableContainer<Apple> appleComparable =  new MyComparableContainer<Apple>(f1);
 31         MyComplicatedContainer<Orange, Sunkist> orangeContainer = new MyComplicatedContainer<Orange, Sunkist>(f2, f3);
 32     }
 33 }
 34 
 35 /**
 36  * A generified class is just like any other class, but includes the ability to use
 37  * types that are determined by the user of the class instead of types specified by
 38  * the class designer.
 39  *
 40  * @author Adam J. Conover
 41  * @param <T>  T is substituted for the class specified by the user of the class.
 42  */
 43 class MySimpleContainer<T> {
 44 
 45     private T data;
 46 
 47     public MySimpleContainer(T data) {
 48         this.setData(data);
 49     }
 50 
 51     /**
 52      * @return the data
 53      */
 54     public T getData() {
 55         return this.data;
 56     }
 57 
 58     /**
 59      * @param data the data to set
 60      */
 61     public void setData(T data) {
 62         this.data = data;
 63     }
 64 }
 65 
 66 /**
 67  * This is a slightly more elaborate example where T is a type which extends another
 68  * type which is also generified.  However, simple substitution can be used to
 69  * figure out what is going on.
 70  *
 71  * @author Adam J. Conover
 72  * @param <T> The user specified type which will replace all occurrences of T.
 73  *            T must be comparable to itself or any of it's super types.
 74  */
 75 class MyComparableContainer<T extends Comparable<? super T>> implements Comparable<T> {
 76 
 77     private T data;
 78 
 79     public MyComparableContainer(T data) {
 80         this.data = data;
 81     }
 82 
 83     /**
 84      * @return the data
 85      */
 86     public T getData() {
 87         return this.data;
 88     }
 89 
 90     /**
 91      * @param data the data to set
 92      */
 93     public void setData(T data) {
 94         this.data = data;
 95     }
 96 
 97     @Override
 98     public int compareTo(T other) {
 99         return this.data.compareTo(other);
100     }
101 }
102 
103 /**
104  * An even more elaborate class declaration which utilizes multiple generic types
105  * and inheritance.
106  *
107  * @author Adam J. Conover
108  * @param <T>  The user specified type which will replace all occurrences of T.
109  *             T must be comparable to itself or any of it's super types.
110  * @param <U>  The user specified type, which extends T, and will replace all
111  *             occurrences of U.
112  */
113 class MyComplicatedContainer<T extends Comparable<? super T>, U extends T> extends MyComparableContainer<T> {
114 
115     private U localData;
116 
117     public MyComplicatedContainer(T parm1, U parm2) {
118         super(parm1);
119         this.localData = parm2;
120     }
121 
122     /**
123      * @return the localData
124      */
125     public U getLocalData() {
126         return localData;
127     }
128 
129     /**
130      * @param localData the localData to set
131      */
132     public void setLocalData(U localData) {
133         this.localData = localData;
134     }
135 
136 }
137