Reputation: 2841
I have the following test code:
FileSystem fs = FileSystems.getDefault();
Path conf = fs.getPath(".");
WatchKey key = null;
try {
WatchService watcher = fs.newWatchService();
conf.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
while(true) {
key = watcher.take(); // waits
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (StandardWatchEventKinds.OVERFLOW == kind) continue;
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path file = ev.context();
System.out.println(file);
}
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
}
The compiler issues an unchecked cast
warning related to the line
WatchEvent<Path> ev = (WatchEvent<Path>)event;
since event
comes out of key.pollEvents()
as a WatchEvent<?>
, and the compiler can't tell if during runtime it's really going to contain a Path
, and not something else.
Regarding this, I was wondering if it's possible to get rid of this warning without explicitly suppressing it. I found some hint, although related to quite different situations, like this, but here it seems that they can control how the generic list is built, while in my case this isn't possible.
I also found this, where they suggest to suppress the warning, checking at the same time if the actual type is the correct one (since the compiler can't do it on its own), but I couldn't manage to do something along these lines in my case. Is it possible? How would you do it?
On the other hand, in my case I'm getting these WatchEvent
's from a WatchService
registered with a Path
object: is this fact alone enough to prove that every WatchEvent<?>
coming out from this WatchService<?>
will have a Path
type implementation? If this is true, can I safely assume that the cast will always be correct and suppress the warning? Is there any way to avoid it without suppressing it in this case?
Thank you very much.
I could have immediately checked the references that explicitly state that:
T context()
Returns the context for the event.
In the case of ENTRY_CREATE, ENTRY_DELETE, and ENTRY_MODIFY events the context is a Path that is the relative path between the directory registered with the watch service, and the entry that is created, deleted, or modified.
So in my case I'm watching for ENTRY_MODIFY
events, hence my T
type is definetely a Path
.
Upvotes: 6
Views: 1279
Reputation: 19682
I think the best option is to just suppress it
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>)event;
it's perfectly safe, it can only be <Path>
and nothing else. The API designer went a little crazy of being too general.
WatchService
is kind of difficult to use. I have the following utility class you might be intereted in
https://github.com/zhong-j-yu/bayou/blob/0.9/src/_bayou/_tmp/_FileMonitor.java
For example
_FileMonitor monitor = new _FileMonitor( ROOT_DIR );
List<Set<Path>> changes = monitor.pollFileChanges( TIMEOUT )
// return 3 sets, [0]=created, [1]=modified, [2]=deleted
Upvotes: 4