Erroneous JavaDoc for Path#register

David M. Lloyd david.lloyd at redhat.com
Thu Dec 4 08:30:08 PST 2008


Actually, I'm wrong, identity comparison does *not* always work on enum 
types because the JDK might make anonymous subtypes for enum constants that 
override a method differently.

And the sad thing is, I've made the same mistaken assumption several times. 
  Will I ever learn? :-)

- DML

On 12/04/2008 10:14 AM, David M. Lloyd wrote:
> I didn't know about the <?> thing with generic varargs.  I've always 
> just avoided it.
> 
> Yeah, I see what you're saying about set creation.  But I think the 
> common usage would be more like:
> 
> register(myWatcher, EnumSet.of(ENTRY_CREATE, ENTRY_DELETE, 
> ENTRY_MODIFY), emptySet());
> 
> (some implied static imports there)
> 
> Yeah, a new set creation method would be helpful for the heterogeneous 
> enum type case - maybe something like one of the following:
> 
>    // use type to locate the right nested enum set - identity comparison 
> on the Class works because of the
>    // nature of enums
>    Set<Enum> aggregate(EnumSet<? extends Enum> one, EnumSet<? extends 
> Enum> two);
>    Set<Enum> aggregate(EnumSet<? extends Enum> one, EnumSet<? extends 
> Enum> two, EnumSet<? extends Enum> three);
>    // ..how many sets before it becomes slower than HashSet?  maybe 
> zero. :-)
> 
>    // Surely doing a simple linear if/else scan of one to perhaps five 
> arguments will be faster than building a
>    // whole hashset?  One notes that Collections.singletonSet() already 
> accommodates the first case
>    Set<T> set(T one);
>    Set<T> set(T one, T two);
>    Set<T> set(T one, T two, T three);
>    Set<T> set(T one, T two, T three, T four);
>    Set<T> set(T one, T two, T three, T four, T five);
> 
> Though I guess I'm going off in a different direction now... :-)
> 
> - DML
> 
> On 12/04/2008 09:45 AM, Matthias Ernst wrote:
>> [moved from my duplicate thread]
>>
>> When you have good Set creation methods, i.e. EnumSet, then that would
>> be a good option IMHO. Or nio could offer these if java.util doesn't
>> get it done. Arrays should go away.
>>
>> new HashSet<Type>(Arrays.asList(a, b, c)) is however not an option.
>>
>> Regarding the generic array problem: if I'm not mistaken, you're safe
>> with <?> . It is trivially always typesafe and the compiler shouldn't
>> warn.
>>
>> Matthias
>>
>>
>> On Thu, Dec 4, 2008 at 4:23 PM, David M. Lloyd 
>> <david.lloyd at redhat.com> wrote:
>>> On 12/04/2008 02:45 AM, Matthias Ernst wrote:
>>>>
>>>> http://openjdk.java.net/projects/nio/javadoc/java/nio/file/Path.html#register(java.nio.file.WatchService,%20java.nio.file.WatchEvent.Kind[],%20java.nio.file.WatchEvent.Modifier...) 
>>>>
>>>>
>>>> Barring any language changes I missed, the example code does not
>>>> compile. It requires an explicit array creation, not?
>>>>
>>>> WatchKey key = dir.register(watcher, new WatchEvent.Kind<?>[] {
>>>>  ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY
>>>> });
>>>>
>>>>
>>>> Given that there are no modifiers defined as of today and I would
>>>> expect them to be empty most of the time (that's why they're called
>>>> modifiers), wouldn't it be nicer if the two parameters were switched?
>>> Unfortunately, if you have a varargs method parameter which is of a 
>>> generic
>>> type, you'll generally get an annoying compile-time warning stating that
>>> you're implicitly creating an array of generic type.  On the other 
>>> hand, the
>>> second parameter actually is an *explicit* generic array creation, 
>>> so...?
>>>
>>> Perhaps it would be better if both of these parameters were Set<> 
>>> types like
>>> this:
>>>
>>> public abstract WatchKey register(WatchService watcher,
>>>                                  Set<WatchEvent.Kind<?>> events,
>>>                                  Set<WatchEvent.Modifier> modifiers)
>>>                           throws IOException;
>>>
>>> This way, one could take advantage of EnumSet by creating enums to 
>>> implement
>>> each interface for a particular provider.  E.g. the standard events 
>>> class
>>> "StandardWatchEventKind" could become:
>>>
>>> /** Typed in an email client, forgive egregious errors */
>>> public class StandardWatchEventKind {
>>>    enum PathKind implements WatchEvent.Kind<Path> {
>>>        // I have no idea if these are the proper names.  Just for
>>> illustration...
>>>        ENTRY_CREATE("create", Path.class),
>>>        ENTRY_DELETE("delete", Path.class),
>>>        ENTRY_MODIFY("modify", Path.class),
>>>        ;
>>>        private final String name;
>>>        private PathKind(String name) {
>>>            this.name = name;
>>>        }
>>>
>>>        public String getName() {
>>>            return name;
>>>        }
>>>
>>>        public Class<Path> getType() {
>>>            return Path.class;
>>>        }
>>>    }
>>>
>>>    enum VoidKind implements WatchEvent.Kind<Void> {
>>>        OVERFLOW("overflow"),
>>>        ;
>>>        private final String name;
>>>        private VoidKind(String name) {
>>>            this.name = name;
>>>        }
>>>
>>>        public String getName() {
>>>            return name;
>>>        }
>>>
>>>        public Class<Void> getType() {
>>>            return Void.class;
>>>        }
>>>    }
>>>
>>>    // Not strictly necessary but maybe desirable?
>>>    public static PathKind ENTRY_CREATE = PathKind.ENTRY_CREATE;
>>>    ...
>>> }
>>>
>>> Then one could use EnumSets for watch event kind sets that are all of 
>>> a type
>>> (which seems like it would be a common situation, no?), and a plain 
>>> HashSet
>>> otherwise.
>>>
>>> - DML
>>>
> 



More information about the nio-dev mailing list