Generic Class Hierarchies
Generic classes can be part of a class hierarchy in just the same way as a non-generic class.
In a generic hierarchy, any type arguments needed by a generic superclass must be passed up the hierarchy by all subclasses.
Using a Generic Superclass
// A simple generic class hierarchy.
class Gen<T> {
T ob;
Gen(T o)
{
ob = o;
}
// Return ob.
T getob()
{
return ob;
}
}
// A subclass of Gen.
class Gen2<T> extends Gen<T> //extends the generic class with type parameter T which is //passed by subclass
{
Gen2(T o)
{
super(o);
}
}
public class Simple
{
public static void main(String args[])
{
Gen2<Integer> num = new Gen2<Integer>(100);
System.out.println("value:"+num.getob());
}
}
Output:
value:100
- A subclass is free to add its own type parameters, if needed.
// A simple generic class hierarchy.
class Gen<T>
{
T ob;
Gen(T o)
{
ob = o;
}
// Return ob.
T getob()
{
return ob;
}
}
// A subclass of Gen that defines a second
// type parameter, called V.
class Gen2<T, V> extends Gen<T>
{
V ob2;
Gen2(T o, V o2)
{
super(o);
ob2 = o2;
}
V getob2()
{
return ob2;
}
}
// Create an object of type Gen2.
public class Simple
{
public static void main(String args[])
{
// Create a Gen2 object for String and Integer.
Gen2<String, Integer> x = new Gen2<String, Integer>("Value is: ", 99);
System.out.print(x.getob());
System.out.println(x.getob2());
}
}
Output:
Value is: 99
A Generic Subclass
- It is perfectly acceptable for a non-generic class to be the superclass of a generic subclass.
// A non-generic class can be the superclass
// of a generic subclass.
// A non-generic class.
class NonGen {
int num;
NonGen(int i) {
num = i;
}
int getnum() {
return num;
}
}
// A generic subclass.
class Gen<T> extends NonGen {
T ob; // declare an object of type T
// Pass the constructor a reference to
// an object of type T.
Gen(T o, int i) {
super(i);
ob = o;
}
// Return ob.
T getob() {
return ob;
}
}
// Create a Gen object.
public class Simple {
public static void main(String args[]) {
// Create a Gen object for String.
Gen<String> w = new Gen<String>("Hello", 47);
System.out.print(w.getob() + " ");
System.out.println(w.getnum());
}
}
Output:
Hello 47
Run-Time Type Comparisons Within a Generic Hierarchy
- instanceof determines if an object is an instance of a class. It returns true if an object is of the specified type or can be cast to the specified type.
- The instanceof operator can be applied to objects of generic classes.
// Use the instanceof operator with a generic class hierarchy.
class Gen<T>
{
T ob;
Gen(T o)
{
ob = o;
}
// Return ob.
T getob()
{
return ob;
}
}
// A subclass of Gen.
class Gen2<T> extends Gen<T>
{
Gen2(T o)
{
super(o);
}
}
// Demonstrate run-time type ID implications of generic
// class hierarchy.
public class Simple
{
public static void main(String args[])
{
// Create a Gen object for Integers.
Gen<Integer> iOb = new Gen<Integer>(88);
// Create a Gen2 object for Integers.
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
// Create a Gen2 object for Strings.
Gen2<String> strOb2 = new Gen2<String>("Generics Test");
// See if iOb2 is some form of Gen2.
if(iOb2 instanceof Gen2<?>)
System.out.println("iOb2 is instance of Gen2");
// See if iOb2 is some form of Gen.
if(iOb2 instanceof Gen<?>)
System.out.println("iOb2 is instance of Gen");
System.out.println();
// See if strOb2 is a Gen2.
if(strOb2 instanceof Gen2<?>)
System.out.println("strOb2 is instance of Gen2");
// See if strOb2 is a Gen.
if(strOb2 instanceof Gen<?>)
System.out.println("strOb2 is instance of Gen");
System.out.println();
// See if iOb is an instance of Gen2, which it is not.
if(iOb instanceof Gen2<?>)
System.out.println("iOb is instance of Gen2");
else
System.out.println("iOb not a instance of Gen2");
// See if iOb is an instance of Gen, which it is.
if(iOb instanceof Gen<?>)
System.out.println("iOb is instance of Gen");
// The following can't be compiled because
// generic type info does not exist at run time.
// if(iOb2 instanceof Gen2<Integer>)
// System.out.println("iOb2 is instance of Gen2<Integer>");
}
}
Output:
iOb2 is instance of Gen2
iOb2 is instance of Gen
strOb2 is instance of Gen2
strOb2 is instance of Gen
iOb not a instance of Gen2
iOb is instance of Gen
Casting
We can cast one instance of a generic class into another only if the two are
- compatible
Type arguments are the same
(Gen <Integer>) iOb2// legal because iOb2 includes an instance of Gen<Integer>
. But, this cast:(Gen <Long>) iOb2// illegal is not legal because iOb2 is not an instance of Gen<Long>
Overriding Methods in a Generic Class
- A method in a generic class can be overridden just like any other method.
// Overriding a generic method in a generic class.
class Gen<T>
{
T ob; // declare an object of type T
// Pass the constructor a reference to
// an object of type T.
Gen(T o)
{
ob = o;
}
// Return ob.
T getob()
{
System.out.print("Gen's getob(): " );
return ob;
}
}
// A subclass of Gen that overrides getob().
class Gen2<T> extends Gen<T>
{
Gen2(T o)
{
super(o);
}
// Override getob().
T getob()
{
System.out.print("Gen2's getob(): ");
return ob;
}
}
// Demonstrate generic method override.
public class Simple
{
public static void main(String args[])
{
// Create a Gen object for Integers.
Gen<Integer> iOb = new Gen<Integer>(88);
// Create a Gen2 object for Integers.
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
// Create a Gen2 object for Strings.
Gen2<String> strOb2 = new Gen2<String> ("Generics Test");
System.out.println(iOb.getob());
System.out.println(iOb2.getob());
System.out.println(strOb2.getob());
}
}
Output:
Gen's getob(): 88
Gen2's getob(): 99
Gen2's getob(): Generics Test