How do you make this work:
public class Frankenstein<T extends IHuman, IMonster>{
}
Without making
public interface Weirdo extends Ihuman, IMonster{
}
Edit
Why is this not working?
public <T> void mapThis(
Class<? extends MyClass<T>> key, Class<? extends T & IDisposable> value) {
}
I am getting compiler message marking Class<? extends T & IDisposable> as an Error.
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:
In fact that’s what came to my mind when I first saw this post. But this actually gives a compiler error:
To help me explain why, I’d like to quote an Oracle Blogs post by Victor Rudometov about this error:
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:
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:
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:
Assuming the caller isn’t explicitly specifying
TandU, this can be reduced to the following:Or just this (subtle difference, but that’s another topic):
This is because
Tdoesn’t have any bounds, so no matter what type of arguments get passed in,Tcan always resolve toObjectat the very least, and so then canU.Let’s go back and say
Tis bounded:This can be reduced in the same way (
Foocould be a class or interface):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:
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:
Here,
Tis inferred to beObject– this matches up with earlier reasoning about simplifying themapThistype parameters. You have to manually specify the type parameters in order to achieve the intended type checking:However, and here’s where your use case starts to come in, it’s a different matter with multiple type parameters with staggered bounds:
Now this call errors:
The tables have turned – we have to manually relax the type parameters to get it to compile:
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).