Java Generics with a Class & an Interface - Together

Java Generics With a Class & an Interface - Together

Actually, you can do what you want. If you want to provide multiple interfaces or a class plus interfaces, you have to have your wildcard look something like this:

<T extends ClassA & InterfaceB>

See the Generics Tutorial at sun.com, specifically the Bounded Type Parameters section, at the bottom of the page. You can actually list more than one interface if you wish, using & InterfaceName for each one that you need.

This can get arbitrarily complicated. To demonstrate, see the JavaDoc declaration of Collections#max, which (wrapped onto two lines) is:

public static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)

why so complicated? As said in the Java Generics FAQ: To preserve binary compatibility.

It looks like this doesn't work for variable declaration, but it does work when putting a generic boundary on a class. Thus, to do what you want, you may have to jump through a few hoops. But you can do it. You can do something like this, putting a generic boundary on your class and then:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
Class<T> variable;
}

to get variable that has the restriction that you want. For more information and examples, check out page 3 of Generics in Java 5.0. Note, in <T extends B & C>, the class name must come first, and interfaces follow. And of course you can only list a single class.

Generic class that extends class and implements interface

T must extend Fragment and implement SomeInterface

In that case you could declare SomeClass as the following:

public class SomeClass<T extends Fragment & SomeInterface>

That would require an object of type T to both extend Fragment and implement SomeInterface.

Further, using my T class, I want to create views, using T.getActivity() as Context.

I'm unfamiliar with Android, but if getActivity() is a public instance method declared in Fragment then will be entirely possible to call it on an instance of T, since the compiler will know all Ts must inherit that method.

Generic which is required to implement two interfaces

you can use Multiple Bounds like <T extends CanFly & CanRun>

Note: in future if you want to add a class along with CanFly & CanRun then make sure to put the class at the beginning like <T extends className & CanFly & CanRun> otherwise it will raise an exception

Java generics - Make Generic to extends 2 interfaces

Reimeus already pointed out that what you're asking for in your edit isn't possible. I'd just like to expand a little on why.

One would think you could use the following:

public <T, U extends T & IDisposable> void mapThis(
Class<? extends MyClass<T>> key,
Class<? extends U> value
) { ... }

In fact that's what came to my mind when I first saw this post. But this actually gives a compiler error:

a type variable may not be followed by other bounds

To help me explain why, I'd like to quote an Oracle Blogs post by Victor Rudometov about this error:

This fact is not always clear, but it is true. The following code
should not compile:

interface I {}

class TestBounds <U, T extends U & I> {

}

Because JLS Chapter 4
Types, Values, and Variables section 4.4 Type Variables states: "The
bound consists of either a type variable, or a class or interface type
T possibly followed by further interface types I1 , ..., In.
". So one
may use T extends U, T extends SomeClass & I, but not T extends U & I.
This rule applies to all cases including type variables and bounds in
methods and constructors.

The reasons for this restriction are explored in a closely related post: Why can't I use a type argument in a type parameter with multiple bounds?

To summarize, the restriction was imposed in order to "preclude certain awkward situations coming into existence" (JLS §4.9).

What kind of awkward situations? An answer by Chris Povirk describes one:

[A reason for the restriction is] the possibility of specifying illegal types. Specifically, extending a generic interface twice with different parameters. I can't come up with a non-contrived example, but:

/** Contains a Comparator<String> that also implements the given type T. */
class StringComparatorHolder<T, C extends T & Comparator<String>> {
private final C comparator;
// ...
}

void foo(StringComparatorHolder<Comparator<Integer>, ?> holder) { ... }

Now holder.comparator is a Comparator<Integer> and a Comparator<String>.

Chris also points to Sun bug 4899305, which was a bug contesting this language restriction. It was closed as Won't Fix with the following comment:

If a type variable could be followed by type variables or by (possibly
parameterized) interfaces, there would likely be more mutually
recursive type variables, which are very difficult to handle. Things
are already complicated when a bound is simply a parameterized type,
e.g. <S,R extends Comparable<S>>. Consequently, bounds are not going
to change now. Both javac and Eclipse agree that S&T and
S&Comparable<S> are illegal.

So those are the reasons behind the restriction. Addressing generic methods specifically (which your question concerns), I'd like to further point out that type inference would theoretically cause such bounds to be pointless anyway.

If we reexamine the type parameters declared in the hypothetical signature above:

<T, U extends T & IDisposable>

Assuming the caller isn't explicitly specifying T and U, this can be reduced to the following:

<T, U extends Object & IDisposable>

Or just this (subtle difference, but that's another topic):

<T, U extends IDisposable>

This is because T doesn't have any bounds, so no matter what type of arguments get passed in, T can always resolve to Object at the very least, and so then can U.

Let's go back and say T is bounded:

<T extends Foo, U extends T & IDisposable>

This can be reduced in the same way (Foo could be a class or interface):

<T extends Foo, U extends Foo & IDisposable>

Based on that reasoning, the syntax you're trying to achieve is pointless as far as restricting the caller to more specific arguments.

Pre-Java 8 addendum:

Prior to Java 8, there is a use case for what you're trying to do. Because of a limitation with how the compiler infers generic method type parameters, my above reasoning to go out the window. Take the following generic method:

class MyClass {
static <T> void foo(T t1, T t2) { }
}

This is a common beginner's mistake of trying to make a method that takes two parameters of the "same type". Of course it's pointless because of the way inheritance works:

MyClass.foo("asdf", 42); // legal

Here, T is inferred to be Object - this matches up with earlier reasoning about simplifying the mapThis type parameters. You have to manually specify the type parameters in order to achieve the intended type checking:

MyClass.<String>foo("asdf", 42); // compiler error

However, and here's where your use case starts to come in, it's a different matter with multiple type parameters with staggered bounds:

class MyClass {
static <T, U extends T> void foo(T t, U u) { }
}

Now this call errors:

MyClass.foo("asdf", 42); // compiler error

The tables have turned - we have to manually relax the type parameters to get it to compile:

MyClass.<Object, Object>foo("asdf", 42); // legal

This happens because of the limited way in which the compiler infers method type parameters. For this reason, what you wanted to achieve would've actually had an application in restricting the caller's arguments.

However, this problem appears to have been fixed in Java 8, and MyClass.foo("asdf", 42) now compiles without any error (thanks to Regent for pointing this out).

How can I define a generic class that implements two interfaces?

You can give multiple bounds to type parameter:

public interface AbstractSortedSimpleList<T extends Comparable<T> & Alike>

Then, your SortedSimpleList would be like:

class SortedSimpleList<T extends Comparable<T> & Alike> implements AbstractSortedSimpleList<T> {}

See JLS §4.4:

Every type variable declared as a type parameter has a bound. If no bound is declared for a type variable, Object is assumed. If a bound is declared, it consists of either:

  • a single type variable T, or

  • a class or interface type T possibly followed by interface types I1 & ... & In.

Note:

You can't have such multiple bounds for wildcards though. It's only for type parameters.

References:

  • Java Generics FAQs - Type Parameter bounds

Generics Inheriting Multiple Interfaces

There's not enough information about Lab and Visit, but I'm going to assume that these are concrete types that are unrelated except that they both implement HasId and HasDate:

class Lab implements HasId, HasDate { ... }
class Visit implements HasId, HasDate { ... }

Given this, you appear to be trying to create a heterogeneous list that can include both Lab and Visit objects. But you can't do this with a concrete type, other than Object, because for any concrete type Concrete, a List<Concrete> cannot contain both Lab and Visit objects. Based on this, I think it's an error to make this method generic with parameter <T extends HasId & HasDate>, since no class type T will work.

What you probably want to do is create a List<InterfaceType> for some interface type. That's the normal way to do things when you want a heterogeneous list where all the objects are expected to implement InterfaceType, but don't need to have anything else in common. Your problem is that you have two interface types, and you want the objects in your list to implement both.

The solution is to define a new interface, instead of making it generic:

interface HasIdAndDate extends HasId, HasDate {
}

and make labsAndVisits a List<HasIdAndDate> instead of List<T>. (You could run into problems if HasId and HasDate define methods with the same name and same parameter types, in which case the best solution is probably to change one of the method names.)

Note: I have not tested this.

Java Generics create list of objects which extends class A and implements interface B

You can also use '&' operator and declare the unknown class as a type parameter like below. The advantage of this vs declaring a class XXX extends B implement A is that your code will work with any such a class that satisfy the constraints not just XXX descendants.

import java.util.*;

interface A {};

class B {};

class Test {

public <T extends B & A> List<T> asList(Collection<T> elements) {
List<T> result = new ArrayList<>(elements.size());
for (T element : elements) result.add(element);
return result;
}
}

Implements interface with generics, both methods have same erasure

The declaration

abstract class BaseClass implements BaseInterface<T>

makes no sense, unless T is an actual class. If it's implementing a generic interface, it needs to either

  • be a generic class, or
  • supply a type argument in place of the generic type parameter.

I believe what you actually wanted to write was

abstract class BaseClass<T> implements BaseInterface<T>

to keep BaseClass as a generic class. You could then declare the other classes as

class ClassA extends BaseClass<MyEntity1> implements MyInterface1 

and

class ClassB extends BaseClass<MyEntity2> implements MyInterface2

Then there would be no clash of the types passed to the baseFunc method.



Related Topics



Leave a reply



Submit