Bounded Wildcard TypesJ8 Home « Bounded Wildcard Types

We saw how we can use Bounded Types to get around the problem with invariance and we then looked at how to allow an unknown type by using Unbounded Wildcard Types in the previous two lessons. What if we had a scenario where we only want a method to work on a particular class or subclasses of it? For this type of situation we can use bounded wildcard types to only allow certain classes to use a method.

Ok, lets start by creating and building some simple classes:


package info.java8;

public class A { 
    {
        System.out.println("A Object initializer"); 
    }
}


package info.java8;

public class B extends A { 
    {
        System.out.println("B Object initializer"); 
    }
}


package info.java8;

public class C extends B {    
    {
        System.out.println("C Object initializer"); 
    }
}


package info.java8;

public class D { // Nothing to do  with other classes    
    {
        System.out.println("D Object initializer"); 
    }
}

Build the classes in the usual way.

Now we need to write a simple generic class that will take any type and have a method within in that will eventually only work on the A class and subclasses of it but first we will let the method work with any type:


package info.java8;

/*
  Simple generic class that accepts any object
*/
public class BoundedWildcardType<T> {

    // Generic object declaration
    private final T genericObj;

    // Pass reference to object of type T to our constructor
    public BoundedWildcardType(T genericObj) {
        this.genericObj = genericObj;
    }

    // Output object type of BoundedWildcardType to console 
    public void showObjectType(BoundedWildcardType<T> obj) {
        System.out.println("Object type of BoundedWildcardType is " + genericObj.getClass().getName());
    }
}

Building the BoundedWildcardType class produces the following output:

Build bounded wilcard type class
Screenshot 1. Building the BoundedWildcardType class.

Now we need to write a test class to show how we can pass various objects to our BoundedWildcardType class:


package info.java8;

/*
  Test our BoundedWildcardType class that accepts any object
*/
public class TestBoundedWildcardType {

    public static void main(String[] args) { 

        // Create some objects
        A a = new A(); 
        B b = new B(); 
        C c = new C(); 
        D d = new D();  
    
        // Test the BoundedWildcardType using A, B, C and D objects
        BoundedWildcardType<A> genAObj = new BoundedWildcardType<>(a);
        genAObj.showObjectType(genAObj);

        BoundedWildcardType<B> genBObj = new BoundedWildcardType<>(b);
        genBObj.showObjectType(genBObj);
 
        BoundedWildcardType<C> genCObj = new BoundedWildcardType<>(c);
        genCObj.showObjectType(genCObj);
 
        BoundedWildcardType<D> genDObj = new BoundedWildcardType<>(d);
        genDObj.showObjectType(genDObj);
    }
}

Running the TestBoundedWildcardType class produces the following output:

Run test bounded wilcard type class
Screenshot 2. Running the TestBoundedWildcardType class.

Well nothing new here, all the classes run as expected. Now we want to change the BoundedWildcardType class so that only objects of type A or sublasses thereof can use the showObjectType(BoundedWildcardType obj) method and for this we need a bounded wildcard type.

Change the signature to showObjectType(BoundedWildcardType<? extends A> obj) as shown below and rebuild the BoundedWildcardType class.


package info.java8;

/*
  Simple generic class that accepts any object
*/
public class BoundedWildcardType<T> {

    // Generic object declaration
    private final T genericObj;

    // Pass reference to object of type T to our constructor
    public BoundedWildcardType(T genericObj) {
        this.genericObj = genericObj;
    }

    // Output object type of BoundedWildcardType to console 
    public void showObjectType(BoundedWildcardType<? extends A> obj) { // Changed to bounded wild card type
        System.out.println("Object type of BoundedWildcardType is " + genericObj.getClass().getName());
    }
}

Rebuilding the TestBoundedWildcardType class after the amendments produces the following output:

Rebuild test bounded wilcard type class
Screenshot 3. Rebuilding the TestBoundedWildcardType class after the amendments .

As you can see from the screenshot above the compiler won't allow us to call the showObjectType(BoundedWildcardType<? extends A> obj) method with an object of class D because the method now has an unbounded wildcard type that only allows the A class and its subclasses.

Remove the creation and call for the genDObj in the TestBoundedType class for the class D type as shown below and rebuild the TestBoundedType class.


package info.java8;

/*
  Test our BoundedWildcardType class that accepts any object
*/
public class TestBoundedWildcardType {

    public static void main(String[] args) { 

        // Create some objects
        A a = new A(); 
        B b = new B(); 
        C c = new C(); 
    
        // Test the BoundedWildcardType using A, B, and C objects
        BoundedWildcardType<A> genAObj = new BoundedWildcardType<>(a);
        genAObj.showObjectType(genAObj);

        BoundedWildcardType<B> genBObj = new BoundedWildcardType<>(b);
        genBObj.showObjectType(genBObj);
 
        BoundedWildcardType<C> genCObj = new BoundedWildcardType<>(c);
        genCObj.showObjectType(genCObj);
    }
}

Rerunning the TestBoundedWildcardType class after the amendments produces the following output:

Rerun test bounded wilcard type class
Screenshot 4. Rerunning the TestBoundedWildcardType class after the amendments.

Related Quiz

Generics Quiz 7 - Bounded Wildcard Types Quiz

Lesson 7 Complete

In this lesson we looked at generic bounded wild card types and how to use them.

What's Next?

In the next lesson we look at generic methods.