Pass in Any Enum into Method - java

I am writing in Java and trying to create a method that will take any Enum class that I pass to it, as described here (mostly):
Java: Generic method for Enums
I am getting a problem when I try to pass an enum into this type of method. It wants me to change the method to take a specific Enum class. Does anyone know what I am doing wrong?
Here is my version of the method:
public Class Presenter{
public static <E extends Enum<E>> List<String> getEnumString(Class<E> eClass){
List<String> returnList = new ArrayList<String>();
for (E en: EnumSet.allOf(eClass)){
returnList.add(en.name());
}
return returnList;
}
}
and here is what I am attempting to pass in. The error is saying that the argument is not applicable, and it suggests changing the method above to only take MyEnumClass:
MyEnumClass eclass;
List<STtring> string = presenter.getEnumString(eclass);
I thank anyone who can help in advance.
Thanks!
-Eli

MyEnumClass eclass;
eClass is a reference to a MyEnumClass object. What you need to pass into your function is the class type itself. The syntax is:
MyEnumClass.class
The following code will do what you want. Notice I pass in MyEnumClass.class, not a variable.
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
public enum MyEnumClass
{
ENUM_1, ENUM_2, ENUM_3, ENUM_4, ENUM_5;
public static void main(String[] args)
{
for (String string : getEnumString(MyEnumClass.class))
System.out.println(string);
}
public static <E extends Enum<E>> List<String>
getEnumString(Class<E> eClass)
{
List<String> returnList = new ArrayList<String>();
for (E en : EnumSet.allOf(eClass))
{
returnList.add(en.name());
}
return returnList;
}
}
Output:
ENUM_1
ENUM_2
ENUM_3
ENUM_4
ENUM_5

Related

How to assign a generic enum in a constructor in java?

I have the following code
import java.util.Arrays;
public class CustomEnum {
//?? varName;
public <E extends Enum<E>> CustomEnum(Class<E> enumClass) {
System.out.println(Arrays.toString(enumClass.getEnumConstants()));
//?? varName = enumClass;
}
}
public enum Mode {
SAMPLE_A,
SAMPLE_B,
SAMPLE_C,
SAMPLE_D
}
and I can call it in this way
public static void main(String[] args) {
CustomEnum customEnum = new CustomEnum(Mode.class);
}
code output
[SAMPLE_A, SAMPLE_B, SAMPLE_C, SAMPLE_D]
What I want to do is assign the value of enumClass to a variable and assign it in the constructor but I don't know which type the variable should be, I tried with multiple ways but I get compilation errors, is this possible?
if the above is not possible, how could I convert a generic type
E[] which is returned by getEnumConstants() to a String[]?
Make the whole class generic, not just the constructor.
public class CustomEnum<E extends Enum<E>> {
private E[] constants;
public CustomEnum(Class<E> enumClass) {
constants = enumClass.getEnumConstants();
}
}

Using parametrized type as generic type in Java

I have a short question concerning Java Genrerics:
Is there any way to get grip on the type of a type-parameter's also generic type? Hard to explain, short example: ;-)
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class GenericContainer<C extends Collection<T>, T> {
C collection;
public GenericContainer(C collection) {
this.collection = collection;
}
// I need both: the type of the collection's elements...
public boolean add(T t) {
return collection.add(t);
}
// ... and the type of the collection.
public C getCollection() {
return this.collection;
}
public static void main(String[] args) {
// Here it comes:
// Is it possible to remove the redundant "String" in the generic declaration?
GenericContainer<List<String>, String> container = new GenericContainer<>(Arrays.asList("Foo", "Bar"));
}
}
So, as said in the comments, my goal is to have this simpler version:
GenericContainer<List<String>> container instead of GenericContainer<List<String>, String> container with redundant String. Any ideas?
Thanks!

Generics, passing wrong types?

What is the difference between the last two statements ? why does one statement work and the other doesn't ?
package Main;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void printIt(List<Object> l)
{
System.out.println(l);
}
public static void main(String[] args) {
List<String> l =new ArrayList<>();
l.add("A");
//what is the differance between the following statments ?
printIt(Arrays.asList("A")); // it compiles successfully
printIt(l); // it does not compile
}
}
The problem is printIt() method expects List<Object> as parameter but we are passing List<String> to it, that's why there is compilation problem.
Replace the parameter List in method printIt() as below:
public static void printIt(List<? extends Object> l)
{
System.out.println(l);
}
Now both will compile,
This is because your method expects a List<Object> and you give it a List<String>.
As weird as it can appear the first time you read this, a List<String> is not a List<Object>.
In your example, you don't modify the content of the lists but let's imagine a method where you want to add a new element.
public static void addIt(List<Object> l, Object o)
{
l.add(o);
}
public static void main(String[] args) {
List<String> l =new ArrayList<>();
l.add("A");
addIt(l, new Integer(1)); // What?! you want to add an Integer to a List<String>!!!!
}
You will have to use wildcards (?) or to solve your problem so your your List .
public static void printIt(List<?> l) //or printIt(List<? extends Object> l)
{
System.out.println(l);
}
The case of printIt(Arrays.asList("A")) is a bit different. It is due to the fact that the generic is determined dynamically, by type inference on a generic method.
List<Object> l = Arrays.asList("A"); //this is valid, the generic type is determined from the type we expect in this declaration.
To help you grok this, here is another compiling code example that demonstrated type inference from return type:
import java.util.*;
// our main class becomes a file but the main method is still found
public class HelloWorld
{
public static void main(String[] args)
{
foo(createList()); // T must be Object
}
private static void foo(List<Object> objs) { }
private static <T> List<T> createList() { return new ArrayList<>(); }
}
so as #csharpfolk mentioned it is all about "Type Inference"!
the following document could be helpful to understand the idea behind that!
https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

How to create a List using the paremetrized type of the generic class as the datype or Object?

Is it anyway possible to create a list by using the parametrized TYPE
of the generic class? In the below code T is the parametrized type.
Any possible solutions?
package collectionsDemo;
import java.util.*;
public class ListDemo<T> {
public void listCreator(){
List<T> listDemo=new ArrayList<>();
/*i intended to add something like below Since
T is type of Integer Object,which i can't perform right now.
and below is the compile time error*/
listDemo.add(34);
listDemo.add(55);
/*The method add(int, T) in the type List<T> is not
applicable for the arguments (int)*/
}
public static void main(String[] args) {
ListDemo<Integer> listdemo=new ListDemo<>();
}
}
No. This is not the way you can do it.
You can not store an int in a list that wants a element of type T.
ListDemo<T> and List<T>, in both these cases, the type parameter T is different.
You need to do this:
List<Integer> listDemo = new ArrayList<>();
Then, and only Then, you cad add integers in your list.
I have been able to answer my own question and i am not sure whether it is best practice or not?Correct me if i am wrong!
*package collectionsDemo;
import java.util.*;
import java.util.Scanner;
public class GenericListCreator<T> {
public void listCreator( T[] e){
List<T> listDemo=new ArrayList<>();
for(T t:e){
listDemo.add(t);
}
for(T t:e){
System.out.println(t);
}
}
public static void main(String[] args) {
GenericListCreator<Integer> age=new GenericListCreator<>();
age.listCreator(new Integer[]{21,22,24});
GenericListCreator<String> name=new GenericListCreator<>();
name.listCreator(new String[]{"John","michell","bing"});
GenericListCreator<Double> price=new GenericListCreator<>();
price.listCreator(new Double[]{23.5,556.5,55.6});
}
}*

Create dynamic Type Java

explain my problem:
I have a super abstract class called First and then I have a lot of class that inherit from it.
I want to build a method that I "say" to it "create a ArrayList of one of the types that inherit from First class", but I'm not to able to find solution.
For example:
public abstract class First{
public First(){
}
}
public class FirstOne extends First{
...........
}
//It's a pseudo-code
public class MyProgramClass{
public creatingMethod(TypeThatInheritFromFirstClass x ){
return ArrayList<TypeThatInheritFromFirstClass>;
}
}
I insert creatingMethod in program class,but it can be anywhere(I prefer in First class like static method, but it's an example)
Thank for your time
You could use a type token:
public class SomeGenerics {
public static void main(String[] args) {
List<SubFirst1> list1 = creatingMethod(SubFirst1.class);
List<SubFirst2> list2 = creatingMethod(SubFirst2.class);
}
public static <T extends First> List<T> creatingMethod(Class<T> type) {
return new ArrayList<>();
}
}
class First {}
class SubFirst1 extends First {}
class SubFirst2 extends First {}
EDIT as per the comment:
As you already have the type token, you can use it for creating instances of that type. A little restriction is, that you must know what constructor to use. If they - for example - all have a parameterless constructor, you can create instances like that:
public static <T extends First> List<T> creatingMethod(Class<T> type) throws ReflectiveOperationException {
List<T> result = new ArrayList<>();
result.add(type.newInstance());
return result;
}
If you have a constructor with parameters (again: all sub classes must have the same parameterized constructor), you must go a more difficult way. Example with a string parameter:
public static <T extends First> List<T> creatingMethod(Class<T> type, String param) throws ReflectiveOperationException {
List<T> result = new ArrayList<>();
Constructor<T> constructor = type.getDeclaredConstructor(String.class);
result.add(constructor.newInstance(param));
return result;
}

Categories

Resources