I have a library method, which returns a collection of Objects by class name.
For example
Iterable x = RunState.getInstance().getMasterContext().getObjects(XAgent.class);
would return a list of all Objects in Context which are InstanceOf XAgent.class
If use it in that way, it work very well. How ever I need a method to pass the class-name to.
public Iterable getObjectsFromContext(Class clazz) {
return RunState.getInstance().getMasterContext().getObjects(clazz);
}
getObjectsFromContext(XAgent.class);
And then it does not work any more, it returns All objects of context... so why it does not pass my "clazz" variable into getObjects() ?
here is the linkt ot javadoc of getObjects();
http://repast.sourceforge.net/docs/api/repast_simphony/repast/simphony/context/Context.html#getObjects-java.lang.Class-
IndexedIterable<T> getObjects(java.lang.Class<?> clazz)
update: this works:
public Iterable getObjectsFromContext(Class<?> clazz) {
return RunState.getInstance().getMasterContext().getObjects(clazz);
}
getObjectsFromContext(XAgent.class)
this worked for me:
public Iterable getObjectsFromContext(Class<?> clazz) {
return RunState.getInstance().getMasterContext().getObjects(clazz);
}
getObjectsFromContext(XAgent.class)
There was a right answer suggested, but I do not see it anymore to accept, that's why I post it on my own.
This won't work because your wrapper function, getObjectsFromContext, explicitly takes in a type of "Class".
Whatever you pass in, it will be interpreted as type "Class" and thus get passed into the getObjects() function as "Class". That will explain why the function returns all objects.
You'll need make your wrapper function generic.
public Iterable<T> getObjectsFromContext(T clazz) {
return RunState.getInstance().getMasterContext().getObjects(clazz);
}
Related
This question is more theoretical (what I want to do is more complicated but this is the part I'm stuck on), so apologies for the contrived example which may not make much sense.
Say I have some class that has methods that return its value in different forms:
public class MyObject {
public String getAsString() {...}
public int getAsInt() {...}
// and so on
}
I'm trying to create a single method to allow me to specify which MyObject method to call via its parameters. Something like:
public <T> T getValue(MyObject obj, Class<T> c) {
if (c == String.class) {
return obj.getAsString();
} else if (c == Integer.class) {
return obj.getAsInt();
} // and so on
}
So then I would like to call this method like this, assuming obj is a MyObject:
String s = getValue(obj, String.class);
int i = getValue(obj, Integer.class);
// and so on
I'm getting the compile error "Type mismatch: cannot convert from String to T" (and likewise for Integer) in the getValue method. Clearly I'm just not understanding generics fully, but I thought this was the general idea behind generics - here I'm specifying (or trying to specify, at least) the real type of T via the parameter c. What am I doing wrong?
If you want to to create a single method with really safe casts - then I would suggest to setup a mapping between the expected type and its respective getter.
Given the MyObject class definition as:
public class MyObject {
public int getIntValue() {
return 42;
}
public String getStringValue() {
return "Answer";
}
}
So that the "accessor" class could look as follows (it can be generalized further if needed):
public class MyObjectAccessor {
private final Map<Class<?>, Function<MyObject, ?>> registry = new HashMap<>();
public Accessor() {
registerGetter(Integer.class, MyObject::getIntValue);
registerGetter(String.class, MyObject::getStringValue);
}
private <T> void registerGetter(Class<T> type, Function<MyObject, T> getter) {
registry.put(type, getter);
}
#SuppressWarnings("unchecked")
public <T> Optional<T> getValue(MyObject obj, Class<T> type) {
return (Optional<T>) ofNullable(registry.get(type)).map(getter -> getter.apply(obj));
}
}
This would allow you to make the behavior much more predictable with a control over the unexpected/missing mapping.
(Here it returns an Optional back, but you can also throw an exception or provide a default value or do something else)
Please note that the cast inside getValue is actually a safe checked cast (even though it was marked with #SuppressWarnings) as the "safety" proof here is a little bit beyond current javac's capability of static code analysys.
First of all, if getAsString and getAsInt are not doing any conversion (such as would be the case if all your values were stored as strings), you probably can reduce your method to this:
public <T> T getValue(MyObject obj) {
return (T) obj.value;
}
This will have an unchecked cast warning, but that's not worse than leaving the typing decision to your caller (so I'd just #SuppressWarnings("unchecked") it). If your caller uses the wrong target type, they will get a ClassCastException at runtime, which I assume goes well with your current contract. But you can keep c.cast(obj.getAsX()) if you want the exception to be raised in your own method.
With the above, your callers would just use:
String s = getValue(obj);
int i = getValue(obj);
If, however, you are actually converting data in getAs... methods, then you will need to cast in your generic getter after dispatching to the correct getAsX method, at least as ProGu suggested (i.e., return c.cast(obj.getAsX()) in each branch).
public class RestResponseDTO<T extends Object> {
private T result;
}
code where I am initializing this:
public RestResponseDTO getObject(String url,Class clz){
Class cv = clz.getClass();
RestResponseDTO<cv> restResponseDTO =restTemplate.getForObject(url,RestResponseDTO.class);
return restResponseDTO;
}
How can I initalize RestResponseDTO in my getObject function depending upon the clz type?
ps- getForObject is spring restTemplate's standard function- http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#getForObject-java.lang.String-java.lang.Class-java.lang.Object...-
You can add method like this:
void init(Class clazz) {
//you initializing logic
}
and call it
RestResponseDTO<cv> restResponseDTO =restTemplate.getForObject(url,RestResponseDTO.class);
restResponseDTO.init(clz);
return restResponseDTO;
PS: Your cv variable will always have same value.
Please try:
ResponseEntity responseEntity = restTemplate.getForObject(url,RestResponseDTO.class);
and
responseEntity.getBody()
will give you Object T.
You can not pass a class with generic parameter to a method that has the parametertype Class<?>, you need something like Type.
One way (the only i am aware of) around is: create a concrete type that includes the generic parameter.
class IntegerResponse extends RestResponse<Integer>{
...
}
That way you can pass IntegerResponse.class
I am working with Java Generic classes (in this example, these are the Collection classes), and Reflection. I would like to be able to use reflection to take in a Class, check if it is an instance of a List, and then invoke the add method to it.
However, I've faced some difficulties in trying to put as the parameters to invoke the method call, and getting the declared method (shown where I put-what???). Both of those method parameter calls, require an object of type Class<?> which is the parameter type of needed for the add methods being invoked, which I don't know, since T itself is a generic.
Any help is appreciated! I apologize if the question is unclear, I tried the best I could to clarify.
static <T> void TestACollection(Class<T> clazz) {
T element=clazz.newInstance();
if(element instanceof List<?>)
Method m=clazz.getDeclaredMethod("add", what??? );
m.invoke(element, what???);
}
I'm guessing what you are trying to do is this:
public static <T> List<T> makeList() {
List<T> list = (List<T>) new ArrayList();
return list;
}
//...
{
List<String> list = makeList();
list.add( "Howdy" );
}
Which works as-is in Java 8. In earlier versions you may have to add #SuppressWarnings("unchecked") to the assignment.
Is there a way to use instanceof based on the passed argument of a method? Example
doSomething(myClass.class); /* I would like to call this also with other classes */
public void doSomething(/*generic parameter that accepts all classes, not just myClass */) {
if (myObject instanceOf /* the generic parameter */ == true) {...}
}
sometimes I'll call the method using myClass.class but other times I would like to call it using someOtherClass.class - I don't want to change the if condition though. Is that possible? If so, how? :)
Thanks
You're looking for the Class.isInstance() method.
public void doSomething(Class<?> c, Object myObject) {
if (c.isInstance(myObject)) {...}
}
This is the way to do it, as far as I know:
public static <T> boolean doInstanceOf(Object object,Class<T> clz) {
return clz.isInstance(object);
}
Usage:
System.out.println(doInstanceOf(myObject,MyClass.class));
In my cache class, I'm going to have a function which writes the serialized version of an object (undecided type) to a file, something like this (generic function):
public <O> void write(O object) {
// ...
serialize(file, object);
// ...
}
Which works great, however, I'm unable to find a way to create a method which can return any object, like the write() method can take any object. Looking for something like this:
public <O> read() {
// ...
O object = unserialize(file);
// ...
return object;
}
Any suggestions on how to accomplish this is highly appreciated!
You specify the return type of type Object:
public Object function(...)
That way the return type will always be of type Object (since all objects are descendants of Object), so they will be accepted.
If you mean
public <O> O read() {
this is almost useless because it is much the same as
public Object read() {
Not sure if I understood the question correctly... You could wrap both methods inside a class and parametrize the class with the object's type, like this:
public class ReaderWriter <T> {
public ReaderWriter(File file) {...}
public void write(T object) {...}
public T read() {...}
}
I would do that by making the whole class generic
class Cache <O extends Serializable> {
public void write(O object) {
serialize(file, object);
}
public O read() {
O object = (O)unserialize(file);
return object;
}
}
Note the cast of the returned object.
Besides that you should use <O extends Serializable> instead of just <O>. This assures that your type parameter id a type that is serializable. This is needed if you want to save (serialize) objects and prevents later errors.
I'm assuming the caller to read() knows which type it expects to get. This is a reasonable assumption because he is going to assign the return value to some variable:
MyType o = read(...); // Caller knows he's going to get a MyType object
If this assumption is true, then you should change the read() method such that it takes a class object:
public<T> T read(Class<T> t) {
...
}
Then the call site will look as follows:
MyType o = read(MyType.class);
Yes,
public <O> O read()
is valid and will do what you want (return any type the caller wants). Whether this is a good idea is another matter