I stumbled upon an interesting error that I've never seen before, and can't explain why
Consider the following class
开发者_如何学Pythonpublic class Sandbox<A,B> {
public void put(B b) {
}
public void put(A a) {
}
}
Looks okay to my eyes. So I compile it and then get this
name clash: put(B) and put(A) have the same erasure
Huh? How do two different generic types have the same signature? There completely separate!
I'm probably missing something completly basic, but I've just not run into this issue before. I've band-aid fixed the problem by calling the methods putA
and putB
, but I'm really curious to why this error happened in the first place.
Would someone mind explaining?
Logically, consider the following code:
SandBox<String, String> sandBox = new SandBox<String, String>();
sandBox.put("foo"); // which put is invoked?
(Although I should admit that it's possible to produce perfectly valid code that produces similar situations - and then a method is chosen at "random".)
Formally, I think this section of the JLS is relevant. Both versions of put have the same argument types - if I read that section correctly.
Generics in Java are only available at code level and not at runtime.
So when the compiler translates your sourcecode, the types you specified for A and B are "erased". This means both types are set to java.lang.Object
.
So you end up with two identical method signatures.
How do two different generic types have the same signature? There completely separate!
Java generics are based on type erasure. That means your code basically compiles to this:
public class Sandbox{
public void put(Object b) {
}
public void put(Object a) {
}
}
Huh? How do two different generic types have the same signature? There completely separate!
The root of your problem appears to be that you do not have a good grasp of Java terminology.
The compiler is not telling you that two generic types have the same signature:
Types (generic or otherwise) don't have signatures in the formal sense. Methods have signatures.
A
andB
are not generic types. They are type parameters.The things that the compiler tells you have the same signature are
put(A)
andput(B)
. These are methods, not types.
EDIT
OK ... so you do understand the terminology.
If you use technical terminology incorrectly, don't be surprised if:
- some people misinterpret your questions (and answers),
- some people call you out for using terminology incorrectly, and
- some people discount what you ask / say as being uninformed.
But the case I'm worried most about (and the real reason I took the time to answer your question!!) is when some poor confused Java newbie does a Google search, finds your SO question full of sloppy terminology, and gets even more confused.
精彩评论