Java use class as parameter

Passing a class with type parameter as type parameter for generic method in Java

Problem summary: I would like to pass a class with a type parameter (such as ArrayList , for example) to a generic method as a type parameter. Let’s say I have a method:

 public static T getGenericObjectFromJson(String json, Class genericType) < // details unimportant, basically returns an object of specified type return JsonParser.fromJson(json, genericType); >

This method, of course, will work perfectly fine for any kind of class. I can call the method like so, for example:

getGenericObjectFromJson(jsonString, User.class) 
getGenericObjectFromJson(jsonString, ArrayList.class) 

Syntactically, this is obviously invalid. However, I am not certain how I would even accomplish something like this. I can, of course, pass ArrayList.class , however the addition of the generic type makes it no longer syntactically valid, and I cannot think of a way around it. The only direct solution has been something like this (which seems rather goofy):

getGenericObjectFromJson(jsonString, new ArrayList().getClass()) 

However we end up losing the generic type anyways, and merely get back an ArrayList of unknown type (though it can be cast). Plus, unnecessarily instantiating an object. My only solution thus far has been to wrap that method in a class that contains a generic type parameter which can be instantiated, like so:

public class JsonDeserializer. 

In this case, the getGenericObjectFromJson method will use the class’s generic type. The Question(s): Ultimately, I am curious why I cannot pass a class with a type parameter, AND whether there is a way to accomplish what I attempted to do. As always, let me know if there are any problems with this question.

Читайте также:  Переформатировать jpg в html

Источник

Pass class type as parameter to use in ArrayList?

I need to write a java method which takes a class (not an object) and then creates an ArrayList with that class as the element of each member in the array. Pseudo-code example:

public void insertData(String className, String fileName) < ArrayListnewList = new ArrayList(); > 

Does it have to be String className ? It’d be easier if you could pass the actual Class object in, like insertData(ExampleClass.class, fileName) .

4 Answers 4

public void insertData(Class clazz, String fileName) < ListnewList = new ArrayList<>(); > 

but if you should use this contract insertData(String className, String fileName) , you cannot use generics because type of list item cannot be resolved in compile-time by Java.

In this case you can don’t use generics at all and use reflection to check type before you put it into list:

public void insertData(String className, String fileName) < List newList = new ArrayList(); Class clazz; try < clazz = Class.forName(className); >catch (ClassNotFoundException e) < throw new RuntimeException(e); // provide proper handling of ClassNotFoundException >Object a1 = getSomeObjectFromSomewhere(); if (clazz.isInstance(a1)) < newList.add(a1); >// some additional code > 

but without information of class you’re able use just Object because you cannot cast your object to UnknownClass in your code.

@VladBochenin I dont know what technique to use, whether its reflection or something else. I just know I need to pass a class into a method, fill an ArrayList of that class with data, and the class is not known until runtime.

@Greymarch maybe I will able to help you more, if will know more context of this tasks. How are you going to create instances of unknown class? Why do you have this restrictions?

My guess is that what you really want to do is to return the generated List . This is what that might look like:

public List loadData(Class clazz, String fileName) < ListnewList = new ArrayList<>(); //. populate list somehow (e.g. with values deserialized from the file named "filename") return newList; > 

This is how it could be used:

List names = loadData(String.class, "someFileContainingNameStrings"); List temperatures = loadData(Double.class, "someFileContainingTemperatureData"); 

Vlad Bochenin gives a good way but it makes no sense to provide a T generic that derives from nothing in your method.
It puts zero constraints in the code of insertData() that manipulates the list.
You will be forced to do cast in the code and it defeats the purpose of Generics.

I suppose you want manipulate some instances of known classes in insertData() .
And if you use generic in your case, it would have more meaningful if you have subtypes of classes to manipulate.

In this way, you could have a method that accepts a base type and its subclases.

public static void insertData(Class clazz, String fileName) < ListnewList = new ArrayList<>(); T t = newList.get(0); // here I can manipulate something that derives from YourClass > 

Источник

Passing Interface Class as a Parameter in Java

Do you really want to pass the Class object, not an instance of some class that implements the IMech interface? That certainly might be what you want, but I can’t tell from the information you provided whether it’s intentional or a design error.

7 Answers 7

public void sendNotification( Class mechanism )  

Because the two classes Class and Class themselves are not related by inheritence, even though IMechanism and EmailNotification are.

You need to make your method accept a Class .

Your parameter mechanism needs to use a bounded wildcard, like so:

public void sendNotification( Class < ? extends IMech >mechanism )

Quoting the generics tutorial link text

In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G is a subtype of G.

Generics don't work that way in Java. What you really need to do it change the method signature to

public void sendNotification( Class < ? extends IMech >mechanism )

Or is that super instead of extends . let me consult Effective Java's Generics chapter.

Here is a mnemonic to help you remember which wildcard type to use: PECS stands for producer-extends, consumer-super.

I'm assuming this will be producing IMech instances, and that extends is correct.

public void sendNotification(IMech mechanism)

so please read some java tutorials about interfaces everyone!

The idea behind interfaces is that you don't need to know which one it is. You should simply be able to pass in an IMech and call its functionality regardless of implementation. Consider the following:

public interface IMech < void sendMessage(); >public class Email implements IMech < @Override void sendMessage() < /* stuff here to send email */ >> 

That's the typical usage pattern for an interface. If you're only using it for an option, perhaps you should consider using an enum instead.

enum IMech < EMAIL, INSTANT_MESSAGE, SNAIL_MAIL, YELL_OVER_CUBICLE >public void sendNotification( IMech mechanism ) < switch(mechanism) < case IMech.EMAIL: // do email .. etc >> foo.sendNotification(IMech.EMAIL); 

Now I know these don't directly answer your questions, but these are the typical forms of usage, and are usually indicative of more adaptable design patterns. After all, do you really need to send in a class object? An enum seems more appropriate if you're merely determining which mechanism to use.

Источник

Passing a class with type parameter as type parameter for generic method in Java

Problem summary: I would like to pass a class with a type parameter (such as ArrayList , for example) to a generic method as a type parameter. Let's say I have a method:

 public static T getGenericObjectFromJson(String json, Class genericType) < // details unimportant, basically returns an object of specified type return JsonParser.fromJson(json, genericType); >

This method, of course, will work perfectly fine for any kind of class. I can call the method like so, for example:

getGenericObjectFromJson(jsonString, User.class) 
getGenericObjectFromJson(jsonString, ArrayList.class) 

Syntactically, this is obviously invalid. However, I am not certain how I would even accomplish something like this. I can, of course, pass ArrayList.class , however the addition of the generic type makes it no longer syntactically valid, and I cannot think of a way around it. The only direct solution has been something like this (which seems rather goofy):

getGenericObjectFromJson(jsonString, new ArrayList().getClass()) 

However we end up losing the generic type anyways, and merely get back an ArrayList of unknown type (though it can be cast). Plus, unnecessarily instantiating an object. My only solution thus far has been to wrap that method in a class that contains a generic type parameter which can be instantiated, like so:

public class JsonDeserializer. 

In this case, the getGenericObjectFromJson method will use the class's generic type. The Question(s): Ultimately, I am curious why I cannot pass a class with a type parameter, AND whether there is a way to accomplish what I attempted to do. As always, let me know if there are any problems with this question.

Источник

Оцените статью