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?










share|improve this question




















  • 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















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?










share|improve this question




















  • 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













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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 6:55









Mureinik

176k22127195




176k22127195










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 so tabs should be Tabs.
    – Little Helper
    Nov 21 at 9:39














  • 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








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












3 Answers
3






active

oldest

votes

















up vote
11
down vote



accepted










You can pass a mapper Function to map enum constants into Strings:



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]





share|improve this answer























  • 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 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




    @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








  • 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


















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);
}





share|improve this answer





















  • 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


















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.






share|improve this answer





















  • 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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















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

























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 Strings:



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]





share|improve this answer























  • 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 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




    @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








  • 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















up vote
11
down vote



accepted










You can pass a mapper Function to map enum constants into Strings:



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]





share|improve this answer























  • 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 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




    @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








  • 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













up vote
11
down vote



accepted







up vote
11
down vote



accepted






You can pass a mapper Function to map enum constants into Strings:



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]





share|improve this answer














You can pass a mapper Function to map enum constants into Strings:



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]






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 at 8:44

























answered Nov 21 at 6:43









Eran

275k36442525




275k36442525












  • 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 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




    @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








  • 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


















  • 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 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




    @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








  • 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
















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












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);
}





share|improve this answer





















  • 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















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);
}





share|improve this answer





















  • 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













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);
}





share|improve this answer












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);
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 6:43









Mureinik

176k22127195




176k22127195












  • 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






  • 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










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.






share|improve this answer





















  • 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















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.






share|improve this answer





















  • 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













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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 9:23









glglgl

65.3k788163




65.3k788163












  • 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










  • @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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Сан-Квентин

8-я гвардейская общевойсковая армия

Алькесар