6

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.

EDIT

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.

Community
  • 1
  • 1
swahnee
  • 2,661
  • 2
  • 24
  • 34
  • The Java compiler guarantees that if your code compiles without any warnings, then it is type safe. Because generics in Java are implemented by erasure, the `` does not exist at runtime and there isn't a way that the compiler can -guarantee- that this cast will be safe, hence the warning. It may well be safe, and if it is you should suppress it, but that is something that only you can figure out. – scottb May 11 '15 at 21:18

1 Answers1

4

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
ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • Thanks for the answer and the suggestion! Btw, I just found that in the official references it's clearly stated that that type can only be a `Path`, as you pointed out, and I've updated the question. – swahnee May 12 '15 at 06:26
  • "difficult to use" is an understatement. I've written a 300 line multi-threaded mess to try and apply deduplication, and light parsing (file deletions cause two events: "MODIFIED" "DELETED", which is silly, just give me the deleted event). Combined with the over-engineered interfaces make this really difficult to work with. – Groostav Sep 15 '16 at 11:02