-2

I came across this type of casting on java oracle tutorial

 for (WatchEvent<?> event: key.pollEvents()) {
...
...
 WatchEvent<Path> ev = (WatchEvent<Path>)event;

My understanding that since the event reference generic type is defined as anything extend Object, so it's self-explained that since Path extends Object indirectly.

But I have searched on java specification about any rules of casting generic type that explains the above case and all related cases but I didn't find anything.

First, is my explanation is right? Second, is there any reference or DOC about this and similar cases?

Community
  • 1
  • 1
Aladdin
  • 1,207
  • 2
  • 16
  • 26
  • 1
    I can't tell which part is not making sense to you or what your actual question is. – takendarkk Jan 01 '17 at 12:14
  • If I remember correctly, casting happens at runtime, but Generics are [erased](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) at compile-time - which would explain why you can't find anything in the JLS on casting Generics (provided I'm right)... – Christian Jan 01 '17 at 12:19
  • @takendarkk , it'a apparent from the title of the question, it's the casting, and I pasted it on the question, it's casting WatchEvent> event to WatchEvent. – Aladdin Jan 01 '17 at 12:20
  • I can see that line of code, I don't understand which part of it is confusing to you. – takendarkk Jan 01 '17 at 12:21
  • I’m not sure what the Java team was thinking when they wrote that cast, considering `Path filename = (Path) event.context();` *is* a safe cast. – VGR Jan 01 '17 at 16:42
  • @VGR I don't think you read my questions well, first I didn't write that line of code, second I don't consider it that it's good to write, and finally look at my question, I just saw that on oracle tutorial and I was wondering about if there is any java specification written about that type of casting! – Aladdin Jan 01 '17 at 17:24
  • Actually, you didn’t read my comment well. “not sure what the Java team was thinking” was putting the blame on the Java team, not you. – VGR Jan 01 '17 at 22:22

2 Answers2

1

You're essentislly asking about this:

WatchEvent<?> event;
WatchEvent<Path> ev = (WatchEvent<Path>)event;

This is a unsafe cast.

The object returned from the poll is an unbounded type. The programmer "knows" the actual type and has (blindly) made the cast.

See JLS 5.1.10 for more detail.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Because WatchEvent<Object> is not a superclass of WatchEvent<Path>, but WatchEvent<?> (which may be thought of as a shorthand for WatchEvent<? extends Object>) is a superclass of WatchEvent<Path>.

Although this may seem counterintuitive at first, it is necessary to use wildcards (?) in this manner to preserve the type safety that generics provide.

Consider what would happen if you assign a List<String> to a List<Object> reference. Then you would be allowed to add(new Object()), violating the type safety.

See also: https://stackoverflow.com/a/2745301/7098259 and https://docs.oracle.com/javase/tutorial/java/generics/unboundedWildcards.html

Community
  • 1
  • 1
Patrick Parker
  • 4,863
  • 4
  • 19
  • 51