Почему WatchService использовать подстановочные непривязанные WatchEvent а не WatchEvent

#java #watchservice

#java #watchservice

Вопрос:

Я просто следовал этому руководству, чтобы использовать WatchService API. Я понятия не имею, почему использовать WatchEvent<?> вместо WatchEvent<Path> , если я использую последний, нет необходимости приводить, или есть какие-либо другие ситуации, которые WatchService можно использовать для мониторинга событий, отличных от пути?

 @SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
    return (WatchEvent<T>)event;
}

void processEvents() {
    for (; ; ) {
        ...
        //why doesn't the poolEvents() return WatchEvent<Path> 
        for (WatchEvent<?> event: key.pollEvents()) {
            WatchEvent.Kind kind = event.kind();

            ...

            //here he use a static method cast() to SuppressWarnings the unchecked warning
            WatchEvent<Path> ev = cast(event);
        }
    }
}
  

Ответ №1:

Javadoc WatchService говорит:

Файловые системы могут сообщать о событиях быстрее, чем они могут быть получены или обработаны, и реализация может налагать неопределенное ограничение на количество событий, которые она может накапливать. Если реализация сознательно отбрасывает события, то она организует метод pollEvents ключа для возврата элемента с типом события ПЕРЕПОЛНЕНИЯ. Это событие может использоваться потребителем в качестве триггера для повторного изучения состояния объекта.

Стандартный набор watcheventkinds.ПЕРЕПОЛНЕНИЕ имеет тип WatchEvent.Kind<Object> , и я считаю, что именно поэтому pollEvents должен возвращать список WatchEvent<?> , а не WatchEvent<Path> . Javadoc для ПЕРЕПОЛНЕНИЯ также упоминает:

Контекст для этого события зависит от реализации и может быть нулевым

именно поэтому тип события переполнения должен быть WatchEvent<Object> .

Обратите внимание, что в руководстве, на которое вы ссылались, предлагается следующее:

Извлеките тип события с помощью метода kind . Независимо от того, для каких событий зарегистрирован ключ, можно получить событие ПЕРЕПОЛНЕНИЯ. Вы можете выбрать обработку переполнения или игнорировать его, но вы должны проверить его.

Поэтому вам следует добавить в свой код следующее (если вы еще этого не сделали):

 if (kind == OVERFLOW) {
    continue;
}