Greetings. This is my first post in this site.
I thought that because of type erasure , one could not expect the following code to compile, and indeed, it did not compile on an earlier version of Eclipse. My understanding was that instanceof was a run-time operator and could not know about the generic type which would be, by run-time, compiled away:
public static <E extends Comparable<? super E>>
void SampleForQuestion(E e)
{
if ( !(e instanceof String) )
System.out.println("I am not a String");
else
System.out.println("I am a String");
}
However, I was surprised to see that one of your threads actually included some code like this in an answer, and my latest Eclipse (Galileo on Windows with JVM 1.6 rev 20) is perfectly happy with it -- and it works, too. (I did notice that someone said it worked on Eclipse but not in another IDE/JDK in that thread, but don't remember the specifics.)
Can someone explain why it works, and more importantly, because I have to guide my students, whether it should be expected to work in the future.
Thank you. (I hope the code formatting comes through correctly - it looks indented correctly from my perspective and there are no tabs.)
What is erased is E
. You can't, in fact, do if (e instanceof E)
, because the type parameter E
is erased. However, String
is not a parameterized type, and e
does have a run-time type, so if (e instanceof String)
works just fine.
instanceof
operator RelationalExpression: RelationalExpression instanceof ReferenceType
The type of a
RelationalExpression
operand of theinstanceof
operator must be a reference type or thenull
type; otherwise, a compile-time error occurs. TheReferenceType
mentioned after theinstanceof
operator must denote a reference type; otherwise, a compile-time error occurs. It is a compile-time error if theReferenceType
mentioned after theinstanceof
operator does not denote a reifiable type (§4.7).
String
is a reifiable type. E
is not.
Because some type information is erased during compilation, not all types are available at run time. Types that are completely available at run time are known as reifiable types. A type is reifiable if and only if one of the following holds:
- It refers to a non-generic type declaration.
- It is a parameterized type in which all type arguments are unbounded wildcards
- It is a raw type.
- It is a primitive type.
- It is an array type whose component type is reifiable.
instanceof
and .class
literal are the two exceptions where raw type in new code can be used That works fine. The method that takes E e
is compiled as Comparable e
, but that doesn't prevent checks against types that exist at runtime ( String
in your example). What you can't do is check for something like ArrayList<String>
(or a generic specialization of your own class), because the ArrayList
type exists at runtime, but ArrayList<String>
does not. Thus, people use hacks like checking the first element of the list.
The lower case e is an object and every object has it's type. You can check instanceof on any object. Read your code with different names and it'll be easier to get:
public static <E extends Comparable<? super E>>
void SampleForQuestion(E paramObject)
{
if ( !(paramObject instanceof String) )
System.out.println("I am not a String");
else
System.out.println("I am a String");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.