Can we define a parameter that allows any type that implements two or more interfaces?
Yes, we can accomplish this by using generic types.
Suppose for example, that we have two interfaces A and B, and two classes, C that implements A and D that implements both A and B, as shown below.
interface A { void foo(); }
interface B { void bar(); }
class C implements A { public void foo() { System.out.println("foo"); } }
class D implements A, B { public void foo() { System.out.println("foo"); } public void bar() { System.out.println("bar"); } }
Now we can define methods like test1() and test2() that restrict the types of values that are passed into the methods using generic types.
For test1(), the type of the value passed is into test1() is defined by T. T is a generic type which represents a placeholder for a set of types. If we used T alone, T would allow any type, which would be no different than declaring the parameter of type Object. We have however constrained the type T by bounding the type. The bounding is declared using <T extends A> before the return type of the method. This bounds the argument to the method to being of any type that implements the interface A. Note that even though A is an interface, we use the extends keyword rather than implements. Since both classes C and D implement A, we can pass instances of C and D to test1().
When we define test2() we bound the parameter to allow any type that implements both A and B using <T extends A & B>. Again, we use extends even though A and B are interfaces, and we use & to separate the interface names. Since only class D implements both A and B, we can only pass instances of D to test2().
class Driver { public static void main(String[] args) { C c = new C(); D d = new D(); test1(c); test1(d);test2(c);// will not compile test2(d); } static <T extends A> void test1(T obj) { obj.foo(); } static <T extends A & B> void test2(T obj) { obj.foo(); obj.bar(); } }