How do I create a generic method to return an array of the enum values instead of its constants?
up vote
12
down vote
favorite
I have an enum with descriptions as String. This is the enum.
public enum tabs
{
A("Actual data"),
B("Bad data"),
C("Can data"),
D("Direct data");
private String description;
tabs(String desc)
{
this.description = desc;
}
public String getDescription()
{
return this.description;
}
}
Now, if I need the data for A, I'd just do
tabs.A.description
I am in the process of creating a generic method to return the values.
I have managed to utilize the below generic method to accept an enum type as the argument.
It returns an array of the enum constants.
But I actually want it to return an array of the values.. ie {"Actual data", "Bad data", "Can data", "Direct data"}.
public static String getActualTabs(Class<? extends Enum<?>> e)
{
return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String::new);
}
What options do I have to achieve this?
java generics enums
add a comment |
up vote
12
down vote
favorite
I have an enum with descriptions as String. This is the enum.
public enum tabs
{
A("Actual data"),
B("Bad data"),
C("Can data"),
D("Direct data");
private String description;
tabs(String desc)
{
this.description = desc;
}
public String getDescription()
{
return this.description;
}
}
Now, if I need the data for A, I'd just do
tabs.A.description
I am in the process of creating a generic method to return the values.
I have managed to utilize the below generic method to accept an enum type as the argument.
It returns an array of the enum constants.
But I actually want it to return an array of the values.. ie {"Actual data", "Bad data", "Can data", "Direct data"}.
public static String getActualTabs(Class<? extends Enum<?>> e)
{
return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String::new);
}
What options do I have to achieve this?
java generics enums
1
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class sotabs
should beTabs
.
– Little Helper
Nov 21 at 9:39
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
I have an enum with descriptions as String. This is the enum.
public enum tabs
{
A("Actual data"),
B("Bad data"),
C("Can data"),
D("Direct data");
private String description;
tabs(String desc)
{
this.description = desc;
}
public String getDescription()
{
return this.description;
}
}
Now, if I need the data for A, I'd just do
tabs.A.description
I am in the process of creating a generic method to return the values.
I have managed to utilize the below generic method to accept an enum type as the argument.
It returns an array of the enum constants.
But I actually want it to return an array of the values.. ie {"Actual data", "Bad data", "Can data", "Direct data"}.
public static String getActualTabs(Class<? extends Enum<?>> e)
{
return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String::new);
}
What options do I have to achieve this?
java generics enums
I have an enum with descriptions as String. This is the enum.
public enum tabs
{
A("Actual data"),
B("Bad data"),
C("Can data"),
D("Direct data");
private String description;
tabs(String desc)
{
this.description = desc;
}
public String getDescription()
{
return this.description;
}
}
Now, if I need the data for A, I'd just do
tabs.A.description
I am in the process of creating a generic method to return the values.
I have managed to utilize the below generic method to accept an enum type as the argument.
It returns an array of the enum constants.
But I actually want it to return an array of the values.. ie {"Actual data", "Bad data", "Can data", "Direct data"}.
public static String getActualTabs(Class<? extends Enum<?>> e)
{
return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String::new);
}
What options do I have to achieve this?
java generics enums
java generics enums
edited Nov 21 at 6:55
Mureinik
177k22127196
177k22127196
asked Nov 21 at 6:38
SteroidKing666
38928
38928
1
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class sotabs
should beTabs
.
– Little Helper
Nov 21 at 9:39
add a comment |
1
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class sotabs
should beTabs
.
– Little Helper
Nov 21 at 9:39
1
1
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class so
tabs
should be Tabs
.– Little Helper
Nov 21 at 9:39
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class so
tabs
should be Tabs
.– Little Helper
Nov 21 at 9:39
add a comment |
3 Answers
3
active
oldest
votes
up vote
11
down vote
accepted
You can pass a mapper Function
to map enum constants into String
s:
public static <T extends Enum<T>> String getActualTabs(Class<T> e, Function<? super T, String> mapper)
{
return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String::new);
}
Usage:
System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));
Output:
[Actual data, Bad data, Can data, Direct data]
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
@SteroidKing666 Using a mapperFunction
argument gives you more flexibility. Fortabs
you want to obtain the values ofgetDescription()
. For some other enum, you might want to obtain the values of a different property (saygetColor()
). If yourserver
enum also hasgetDescription()
, you can passserver::getDescription
. If you only want to supportgetDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).
– Eran
Nov 21 at 7:11
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replacetabs::getDescription
withe -> e.getDescription()
. This will work for any enum that has agetDescription
method that returns aString
.
– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
@Eran Just found out it on my own:.getEnumConstants()
is a method for allClass<>
es. If it is not an enum type, it just returnsnull
, so your function throws a NPE. So while the<T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.
– glglgl
Nov 21 at 8:43
|
show 18 more comments
up vote
4
down vote
I'd first pull getDescription
out to an interface and make sure all your project's enums implement it:
public interface HasDescription {
String getDescription();
}
And then, use it in your generic method:
public static String getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
return Arrays.stream(e.getEnumConstants())
.map(HasDescription::getDescription)
.toArray(String::new);
}
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)
– Eran
Nov 21 at 9:00
add a comment |
up vote
0
down vote
Both answers are quite beautiful.
But there is another variant which might be more superior because it is even more widely usable:
public static <T> String getActualTabs(T values, Function<? super T, String> mapper) {
return Arrays.stream(values)
.map(mapper)
.toArray(String::new);
}
public static <T extends HasDescription> String getActualTabs(T values) {
return Arrays.stream(values)
.map(HasDescription::getDescription)
.toArray(String::new);
// or just: return getActualTabs(values, HasDescription::getDescription);
}
This implementation has the benefit that we don't have to mess around with reflection.
Instead, you would call them this way:
String tabs1 = getActualTabs(Tabs.values())
String tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)
Note that it might be useful to rename the functions, e. g. getStringifiedValues()
or toDescriptions()
.
Disclaimer: untested, but should work, IMHO.
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with{EnumType}.values()
everywhere. If you are restricted to this signature, you can call.values()
resp..getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.
– glglgl
Nov 21 at 10:46
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
accepted
You can pass a mapper Function
to map enum constants into String
s:
public static <T extends Enum<T>> String getActualTabs(Class<T> e, Function<? super T, String> mapper)
{
return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String::new);
}
Usage:
System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));
Output:
[Actual data, Bad data, Can data, Direct data]
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
@SteroidKing666 Using a mapperFunction
argument gives you more flexibility. Fortabs
you want to obtain the values ofgetDescription()
. For some other enum, you might want to obtain the values of a different property (saygetColor()
). If yourserver
enum also hasgetDescription()
, you can passserver::getDescription
. If you only want to supportgetDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).
– Eran
Nov 21 at 7:11
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replacetabs::getDescription
withe -> e.getDescription()
. This will work for any enum that has agetDescription
method that returns aString
.
– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
@Eran Just found out it on my own:.getEnumConstants()
is a method for allClass<>
es. If it is not an enum type, it just returnsnull
, so your function throws a NPE. So while the<T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.
– glglgl
Nov 21 at 8:43
|
show 18 more comments
up vote
11
down vote
accepted
You can pass a mapper Function
to map enum constants into String
s:
public static <T extends Enum<T>> String getActualTabs(Class<T> e, Function<? super T, String> mapper)
{
return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String::new);
}
Usage:
System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));
Output:
[Actual data, Bad data, Can data, Direct data]
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
@SteroidKing666 Using a mapperFunction
argument gives you more flexibility. Fortabs
you want to obtain the values ofgetDescription()
. For some other enum, you might want to obtain the values of a different property (saygetColor()
). If yourserver
enum also hasgetDescription()
, you can passserver::getDescription
. If you only want to supportgetDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).
– Eran
Nov 21 at 7:11
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replacetabs::getDescription
withe -> e.getDescription()
. This will work for any enum that has agetDescription
method that returns aString
.
– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
@Eran Just found out it on my own:.getEnumConstants()
is a method for allClass<>
es. If it is not an enum type, it just returnsnull
, so your function throws a NPE. So while the<T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.
– glglgl
Nov 21 at 8:43
|
show 18 more comments
up vote
11
down vote
accepted
up vote
11
down vote
accepted
You can pass a mapper Function
to map enum constants into String
s:
public static <T extends Enum<T>> String getActualTabs(Class<T> e, Function<? super T, String> mapper)
{
return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String::new);
}
Usage:
System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));
Output:
[Actual data, Bad data, Can data, Direct data]
You can pass a mapper Function
to map enum constants into String
s:
public static <T extends Enum<T>> String getActualTabs(Class<T> e, Function<? super T, String> mapper)
{
return Arrays.stream(e.getEnumConstants()).map(mapper).toArray(String::new);
}
Usage:
System.out.println(Arrays.toString(getActualTabs(tabs.class,tabs::getDescription)));
Output:
[Actual data, Bad data, Can data, Direct data]
edited Nov 21 at 8:44
answered Nov 21 at 6:43
Eran
276k36443529
276k36443529
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
@SteroidKing666 Using a mapperFunction
argument gives you more flexibility. Fortabs
you want to obtain the values ofgetDescription()
. For some other enum, you might want to obtain the values of a different property (saygetColor()
). If yourserver
enum also hasgetDescription()
, you can passserver::getDescription
. If you only want to supportgetDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).
– Eran
Nov 21 at 7:11
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replacetabs::getDescription
withe -> e.getDescription()
. This will work for any enum that has agetDescription
method that returns aString
.
– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
@Eran Just found out it on my own:.getEnumConstants()
is a method for allClass<>
es. If it is not an enum type, it just returnsnull
, so your function throws a NPE. So while the<T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.
– glglgl
Nov 21 at 8:43
|
show 18 more comments
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
@SteroidKing666 Using a mapperFunction
argument gives you more flexibility. Fortabs
you want to obtain the values ofgetDescription()
. For some other enum, you might want to obtain the values of a different property (saygetColor()
). If yourserver
enum also hasgetDescription()
, you can passserver::getDescription
. If you only want to supportgetDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).
– Eran
Nov 21 at 7:11
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replacetabs::getDescription
withe -> e.getDescription()
. This will work for any enum that has agetDescription
method that returns aString
.
– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
@Eran Just found out it on my own:.getEnumConstants()
is a method for allClass<>
es. If it is not an enum type, it just returnsnull
, so your function throws a NPE. So while the<T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.
– glglgl
Nov 21 at 8:43
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
This definitely works. Thanks. I do have a related question though. Let's say I have to pass in different enums. What becomes of the mapper argument then? tabs.class is one enum. Let's say I also have servers.class as another enum. And I have to pass in a generic for the mapper argument. How do I tackle such a situation? How can tabs:getDescription be also converted into generic? I mean I want to get rid of the hardcoded tabs::getDescription and make it so such that I can pass in any enum... sort of like: <enum.name>::getDescription
– SteroidKing666
Nov 21 at 7:05
2
2
@SteroidKing666 Using a mapper
Function
argument gives you more flexibility. For tabs
you want to obtain the values of getDescription()
. For some other enum, you might want to obtain the values of a different property (say getColor()
). If your server
enum also has getDescription()
, you can pass server::getDescription
. If you only want to support getDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).– Eran
Nov 21 at 7:11
@SteroidKing666 Using a mapper
Function
argument gives you more flexibility. For tabs
you want to obtain the values of getDescription()
. For some other enum, you might want to obtain the values of a different property (say getColor()
). If your server
enum also has getDescription()
, you can pass server::getDescription
. If you only want to support getDescription()
method, you can use something like Mureinik's answer (i.e. require that the enum implement some interface).– Eran
Nov 21 at 7:11
2
2
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replace
tabs::getDescription
with e -> e.getDescription()
. This will work for any enum that has a getDescription
method that returns a String
.– Eran
Nov 21 at 7:23
@SteroidKing666 if you are concerned about having to specify the enum name in the method reference, you can use a lambda expression instead : replace
tabs::getDescription
with e -> e.getDescription()
. This will work for any enum that has a getDescription
method that returns a String
.– Eran
Nov 21 at 7:23
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
Okay so getActualTabs(enumName,e->getDescription()) should work. What if enumName is of type Class<? extends Enum<?>> class1 ? That is, I am accepting class1 as a generic enum into a method. And then passing that generic enum class1 into getActualTabs. Because then getActualTabs(class1,e->getDescription()) wouldn't work.
– SteroidKing666
Nov 21 at 7:48
1
1
@Eran Just found out it on my own:
.getEnumConstants()
is a method for all Class<>
es. If it is not an enum type, it just returns null
, so your function throws a NPE. So while the <T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.– glglgl
Nov 21 at 8:43
@Eran Just found out it on my own:
.getEnumConstants()
is a method for all Class<>
es. If it is not an enum type, it just returns null
, so your function throws a NPE. So while the <T extends Enum<T>>
isn't absolutely necessary to make it compile, it is better to have it, because it prevents NPEs on misuse.– glglgl
Nov 21 at 8:43
|
show 18 more comments
up vote
4
down vote
I'd first pull getDescription
out to an interface and make sure all your project's enums implement it:
public interface HasDescription {
String getDescription();
}
And then, use it in your generic method:
public static String getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
return Arrays.stream(e.getEnumConstants())
.map(HasDescription::getDescription)
.toArray(String::new);
}
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)
– Eran
Nov 21 at 9:00
add a comment |
up vote
4
down vote
I'd first pull getDescription
out to an interface and make sure all your project's enums implement it:
public interface HasDescription {
String getDescription();
}
And then, use it in your generic method:
public static String getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
return Arrays.stream(e.getEnumConstants())
.map(HasDescription::getDescription)
.toArray(String::new);
}
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)
– Eran
Nov 21 at 9:00
add a comment |
up vote
4
down vote
up vote
4
down vote
I'd first pull getDescription
out to an interface and make sure all your project's enums implement it:
public interface HasDescription {
String getDescription();
}
And then, use it in your generic method:
public static String getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
return Arrays.stream(e.getEnumConstants())
.map(HasDescription::getDescription)
.toArray(String::new);
}
I'd first pull getDescription
out to an interface and make sure all your project's enums implement it:
public interface HasDescription {
String getDescription();
}
And then, use it in your generic method:
public static String getActualTabs(Class<? extends Enum<?> & HasDescription> e) {
return Arrays.stream(e.getEnumConstants())
.map(HasDescription::getDescription)
.toArray(String::new);
}
answered Nov 21 at 6:43
Mureinik
177k22127196
177k22127196
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)
– Eran
Nov 21 at 9:00
add a comment |
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)
– Eran
Nov 21 at 9:00
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
I get the idea. But somehow I am getting the following error: Incorrect number of arguments for type Class<T>; it cannot be parameterized with arguments <? extends Enum<?>, Script1.HasDescription>. My enums and the HasDescription interface are all within the same class.
– SteroidKing666
Nov 21 at 8:11
1
1
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.
Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)– Eran
Nov 21 at 9:00
I think you'll have to re-write this with a generic type variable, since wildcards can only have a single type bound (i.e.
Class<? extends Enum<?> & HasDescription> e
doesn't pass compilation)– Eran
Nov 21 at 9:00
add a comment |
up vote
0
down vote
Both answers are quite beautiful.
But there is another variant which might be more superior because it is even more widely usable:
public static <T> String getActualTabs(T values, Function<? super T, String> mapper) {
return Arrays.stream(values)
.map(mapper)
.toArray(String::new);
}
public static <T extends HasDescription> String getActualTabs(T values) {
return Arrays.stream(values)
.map(HasDescription::getDescription)
.toArray(String::new);
// or just: return getActualTabs(values, HasDescription::getDescription);
}
This implementation has the benefit that we don't have to mess around with reflection.
Instead, you would call them this way:
String tabs1 = getActualTabs(Tabs.values())
String tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)
Note that it might be useful to rename the functions, e. g. getStringifiedValues()
or toDescriptions()
.
Disclaimer: untested, but should work, IMHO.
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with{EnumType}.values()
everywhere. If you are restricted to this signature, you can call.values()
resp..getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.
– glglgl
Nov 21 at 10:46
add a comment |
up vote
0
down vote
Both answers are quite beautiful.
But there is another variant which might be more superior because it is even more widely usable:
public static <T> String getActualTabs(T values, Function<? super T, String> mapper) {
return Arrays.stream(values)
.map(mapper)
.toArray(String::new);
}
public static <T extends HasDescription> String getActualTabs(T values) {
return Arrays.stream(values)
.map(HasDescription::getDescription)
.toArray(String::new);
// or just: return getActualTabs(values, HasDescription::getDescription);
}
This implementation has the benefit that we don't have to mess around with reflection.
Instead, you would call them this way:
String tabs1 = getActualTabs(Tabs.values())
String tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)
Note that it might be useful to rename the functions, e. g. getStringifiedValues()
or toDescriptions()
.
Disclaimer: untested, but should work, IMHO.
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with{EnumType}.values()
everywhere. If you are restricted to this signature, you can call.values()
resp..getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.
– glglgl
Nov 21 at 10:46
add a comment |
up vote
0
down vote
up vote
0
down vote
Both answers are quite beautiful.
But there is another variant which might be more superior because it is even more widely usable:
public static <T> String getActualTabs(T values, Function<? super T, String> mapper) {
return Arrays.stream(values)
.map(mapper)
.toArray(String::new);
}
public static <T extends HasDescription> String getActualTabs(T values) {
return Arrays.stream(values)
.map(HasDescription::getDescription)
.toArray(String::new);
// or just: return getActualTabs(values, HasDescription::getDescription);
}
This implementation has the benefit that we don't have to mess around with reflection.
Instead, you would call them this way:
String tabs1 = getActualTabs(Tabs.values())
String tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)
Note that it might be useful to rename the functions, e. g. getStringifiedValues()
or toDescriptions()
.
Disclaimer: untested, but should work, IMHO.
Both answers are quite beautiful.
But there is another variant which might be more superior because it is even more widely usable:
public static <T> String getActualTabs(T values, Function<? super T, String> mapper) {
return Arrays.stream(values)
.map(mapper)
.toArray(String::new);
}
public static <T extends HasDescription> String getActualTabs(T values) {
return Arrays.stream(values)
.map(HasDescription::getDescription)
.toArray(String::new);
// or just: return getActualTabs(values, HasDescription::getDescription);
}
This implementation has the benefit that we don't have to mess around with reflection.
Instead, you would call them this way:
String tabs1 = getActualTabs(Tabs.values())
String tabs2 = getActualTabs(Tabs.values(), Tabs::getDescription)
Note that it might be useful to rename the functions, e. g. getStringifiedValues()
or toDescriptions()
.
Disclaimer: untested, but should work, IMHO.
answered Nov 21 at 9:23
glglgl
65.4k788163
65.4k788163
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with{EnumType}.values()
everywhere. If you are restricted to this signature, you can call.values()
resp..getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.
– glglgl
Nov 21 at 10:46
add a comment |
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with{EnumType}.values()
everywhere. If you are restricted to this signature, you can call.values()
resp..getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.
– glglgl
Nov 21 at 10:46
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
How would I implement this if I have another generic method called private <T> void verifyTabData(Class<? extends Enum<?>> class1) which holds the getActualTabs method? I am passing in different sets of enums into this root method.
– SteroidKing666
Nov 21 at 9:26
@SteroidKing666 If all what makes the difference is the list of values, you can work with
{EnumType}.values()
everywhere. If you are restricted to this signature, you can call .values()
resp. .getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.– glglgl
Nov 21 at 10:46
@SteroidKing666 If all what makes the difference is the list of values, you can work with
{EnumType}.values()
everywhere. If you are restricted to this signature, you can call .values()
resp. .getEnumConstants()
in this function. Or you would resort to the original alternative in order not to disturb the original concept completely.– glglgl
Nov 21 at 10:46
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53406480%2fhow-do-i-create-a-generic-method-to-return-an-array-of-the-enum-values-instead-o%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Suggestion to improvement: In Java, the classes are capitalized, e.g., String, Integer, and Class. Enum is just a constant class so
tabs
should beTabs
.– Little Helper
Nov 21 at 9:39