The definition is: https://developer.android.com/reference/java/util/EnumSet
noneOf(Class<E> elementType)
Creates an empty enum set with the specified element type.
But why does it require Class<E>
and not, say, T as in noneOf(T elementType)
?
Is it because it requires the type to be entered at runtime?
But when I write code for example EnumSet.noneOf(Authority.class);
I know the type (Authority) at compile time,so could it have been EnumSet.noneOf(Authority)
?
Since it seems to require though,why not use the anytype as in Class<?>
CodePudding user response:
I know the type (Authority) at compile time,so could it have been
EnumSet.noneOf(Authority)
?
You can't do EnumSet.noneOf(Authority)
because that's not legal Java. When you want to pass around a type then you use a Class
instance, and when you know the needed class at compile-time, you use a class literal (e.g., Authority.class
).
But why does it require
Class<E>
and not, say, T as innoneOf(T elementType)
?
Conceptually, it makes no sense to require an instance of a type when you want an empty set of said type. But then I suppose the question becomes, "Why is any argument needed in the first place?". After all, you can do something like:
Set<String> list = new HashSet<>();
Without passing a Class
instance.
The reason is because EnumSet
is a highly specialized Set
implementation. It needs to know of all the existing enum
constants, which can be queried using the Class
, even when the set is empty. Also, the implementation only works with a single type. An EnumSet
cannot contain constants from different enum
types. The Class
allows the implementation to enforce this.
Other methods, such as EnumSet#of(E)
, don't require a Class
because they require instances of the enum
(i.e., one or more constants) and the type can be grabbed from them.
Since it seems to require though,why not use the anytype as in Class<?>
Because a Class<?>
would allow you to pass any type, not just an enum
type. Though of course that could be solved by bounding the wildcard: Class<? extends Enum<?>>
. Now only enum
types are allowed, but the static type system has no idea which enum
type you're using. This means methods such as noneOf
would only be capable of returning an EnumSet<?>
, which is not very useful.
By declaring a type variable E
and bounding it to extend Enum<E>
, the use of Class<E>
forces you to pass an enum
type and you get an EnumSet<E>
back.
CodePudding user response:
The other answers don't seem to give charitable interpretations of your question, so I'll add one.
But why does it require Class and not, say, T as in noneOf(T elementType) ?
It's because the EnumSet needs to be able to verify the type later. For example:
var set = EnumSet.noneOf(Authority.class);
set.add(Authority.ADMIN); // ordinal 1
On the second line, the set needs to verify that enum being added to the set is the same type as the others. There wouldn't be a way to check the types match if someone later wrote:
set.add(Color.BLUE) // ordinal 1, oops!
It wouldn't be possible to distinguish the problem without the enum class. You ask a valid question of why this should be the type with (lightly rewritten):
EnumSet.noneOf(Authority.ADMIN)
This would be possible, except it wouldn't work for empty enums:
enum Empty {}
Finally, it's important to note the values from each enum may have different classes:
enum Authority {
ADMIN {
@Override void checkPermissions() {...}
},
USER {
@Override void checkPermissions() {...}
};
abstract void checkPermissions();
}
assert Authority.ADMIN.getClass() != Authority.USER.getClass();
As a result, the outermost class needs to be passed into EnumSet
, so the class object is preferred.