You have some misunderstandings about java.
You seem to expect that, given:
interface MyMap extends Map<String, String[]> {}
That you've made an ontological declaration: You seem to think this means:
"I henceforth decree that all things that are a Map<String, String[]>
are also MyMap
s."
Or possibly you think this means:
"I have created an alias; MyMap
is just shorthand for Map<String, String[]>
".
Neither is true.
The correct meaning is:
I created an entirely brand new interface called MyMap
. Any MyMap is necessarily a Map<String, String[]>, but the reverse need not be true. Right now, other than what that Map interface demands you have as methods, I make no further demands. The only objects that are MyMap
s are any objects created by writing new X()
, where X is a class that explicitly has implements MyMap
on it, or is a subclass of a class that did that.
And therefore, it is completely useless in trying to address your problem here.
Your second misunderstanding is generics.
Generics are primarily a figment of the compiler's imagination. They are compiler-checked comments. Seriously. Go check:
Map<?, ?> = new HashMap<String, String>();
and
Map<?, ?> = new HashMap<Integer, Integer>();
compile both, and do a binary diff on the result. Exactly the same bytes. Thus clearly proving that the <String, String>
part does not survive compilation.
This is called erasure. There where generics appears in reflectively accessible stuff, such as in the return type of a method, or the parameter of a method, or some type in an extends clause, or a field's type - it is stored in the class file, but as a comment (as in, the JVM itself doesn't even look at it and cares absolutely not one iota about it). The comment is there for javac
to look at, and use when compiling other code that references these fields/methods/classes.
But everywhere else? javac uses it to generate warnings, errors, and silently inject a few casts, and then it disappears.
Thus, this:
x instanceof Map<String, String>
is impossible.
You just can't check that. x
knows that it is a Map
. It has no idea what the generics are, though.
The solution then is to take a step back.
You had some unknown problem X, and you thought: I know! I'll write a method that takes any object, and then I'll check if the passed-in object is a Map<String, String>
, and then I'll solve my unknown problem X! Except I don't know how to check for that so I'll ask on SO.
But this is a dead end. Go back and re-ask about 'unknown problem X'. I'm positive it can be solved, and quite easily at that, but not like this.
A wild stab at a possible solution for you
If you're looking to eliminate code duplication, and the duplicated code you're trying to deduplicate is the pre
and post
in:
public void someMethod(SomeSpecificType x) {
pre();
customStuffUniqueToThisType();
post();
}
// and 20 more of these, with the same pre and post everywhere
Then perhaps consider lambdas. You could make this method:
public <T> void apply(T obj, Consumer<T> runner) {
pre();
runner.consume(obj);
post();
}
and you can then call it:
Map<String, String> obj = ....;
apply(obj, o -> {
// o is a Map<String, String>.
// do whatever you want here.
});