问题
How can I have a method with two parameters, with both parameters having the same concrete type?
For example,
boolean equals(Object a, Object b)
allows for a of any type and b of any type.
I want to force such that a and b have the same concrete type. I tried
<T> boolean equals(T a, T b)
and inputting a Date and a String to that method, expecting a compile-time error, but I get no errors, since T will resolve to ? extends Serializable & Comparable, since both Date and String implements Serializable and Comparable.
回答1:
You can't, basically. There's no way of doing that. Even if you could do it for a simple call to prohibit arguments of different types, it could always be bypassed using a cast:
equals((Object) date, (Object) string)
If you're interested in the execution-time types of the arguments, you can only test that at execution time. There's no way of the compiler knowing whether an argument of type Date has a value which is a reference to precisely a java.util.Date or some subclass.
回答2:
The thing is your method's signature becomes
<? extends Object> boolean equals(? extends Object a, ? extends Object b)
which doesn't give you any options. Even if you call
equals(new Date(), "hello world");
the compiler doesn't even need to break a sweat and determine the lowest common ancestor for your parameter types.
Edit
Interesting fact. I knew what I wrote above was true, but it still looked a bit weird. So I tested
<T> boolean equals(T a, T b) {
return true;
}
<T,E> boolean equals(T a, E b) {
return true;
}
Which the compiler yelled at. The reason is that the compiler indeed doesn't make a difference and just rewrites both methods as
boolean equals(? extends Object a, ? extends Object b)
which after type erasure becomes
boolean equals(Object a, Object b)
which is the exact same signature. Indeed, if I keep your method equals(T,T) and I add another method with signature equals(Object, Object) the compiler continues to say that I have the same method declared elsewhere.
Long story short, your method equals(T,T) is the same as equals(Object, Object) due to type erasure and thus you can't force the same parameter type, at least at compile time, unless you specifically implement equals methods for each.
来源:https://stackoverflow.com/questions/25867191/forcing-two-parameters-of-a-generic-method-to-have-the-same-concrete-type