I need to grab a int from a object[][], but have no idea how to do it with reflection.
I used this method to grab it from an object[]
public static Object getInterfaceObject(String clazz, String field, Object obj, int index) {
try {
Client client = Boot.client;
ClassLoader cl = client.classLoader;
Class<?> c = cl.loadClass(clazz);
Field f = c.getDeclaredField(field);
f.setAccessible(true);
Object arr = f.get(client.getClient());
return (Object) Array.get(arr, index);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Since this next one is object[][], I don't know how to go about it.
I want to basically be able to do
getInterfaceObject()[arg1][arg2].otherStuff();
You can downcast the Object to Object[][] like this:
((Object[][]) getInterfaceObject())[arg1][arg2].otherStuff();
Or do that inside getInterfaceObject:
public static Object[][] getInterfaceObject(String clazz, String field, Object obj, int index) {
try {
Client client = Boot.client;
ClassLoader cl = client.classLoader;
Class<?> c = cl.loadClass(clazz);
Field f = c.getDeclaredField(field);
f.setAccessible(true);
Object arr = f.get(client.getClient());
return (Object[][]) Array.get(arr, index);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
And leave your callsite as you desired:
getInterfaceObject()[arg1][arg2].otherStuff();
A few of my opinions on clean code (take or leave of course):
Prefer throw new RuntimeException(e); to e.printStackTrace(); (alter the IDE template)
Prefer explicit code to reflection. Reflection loses type safety.
Prefer specific types to Object
Related
description:
I need use getMethod, it requires the parameterTypes.
The origin method requires double (a primitive type, not Double), and I can't change origin method.
I can't just input double.class in parameterTypes, because the s maybe diffierent types, such as Integer(not int).
The method parameter in Foo.java are always and only primitive types.
code:
test.java
public static void main( String args[] )
{
Object obj = new Foo();
Object s = 1.2;
String type = "Double";
try {
Method method = obj.getClass().getMethod("return" + type, s.getClass());// got NoSuchMethodException here, because it requires `double` not Double
System.out.println(method.invoke(obj,s));
} catch (NoSuchMethodException | IllegalAccessException |InvocationTargetException e) {
e.printStackTrace();
}
}
}
Foo.java //(I can't change/add code/delete in this part)
public class Foo {
public double returnDouble(double type){
return type;
}
public int returnInt(int type){
return type;
}
}
what I have tried:
Use Map
public static void main( String args[] )
{
Object obj = new Foo();
// Object s = 1;
// String type = "Int";
Object s = 1.2;
String type = "Double";
Map<String, Class> methodClassMap = new HashMap<String, Class>() {{
put("Double",double.class);
put("Integer",int.class);
}};
try {
Method method = obj.getClass().getMethod("return" + type, methodClassMap.get(s.getClass().getSimpleName()));
System.out.println(method.invoke(obj,s));
} catch (NoSuchMethodException | IllegalAccessException |InvocationTargetException e) {
e.printStackTrace();
}
}
}
It worked, but I have to list all possible type of value the s.
question:
Any better solution than using Map? Maybe use generic?
When you know beforehand that the target method always uses a primitive types, you can use the unwrap() method of MethodType of the java.lang.invoke package.
Object obj = new Foo();
Object s = 1.2;
String type = "Double";
try {
MethodType mt = MethodType.methodType(s.getClass(), s.getClass()).unwrap();
Method method = obj.getClass().getMethod("return" + type, mt.parameterArray());
System.out.println(method.invoke(obj, s));
} catch(ReflectiveOperationException e) {
e.printStackTrace();
}
Alternatively, when you’re already using the method type of the java.lang.invoke package, you can also use a method handle to perform the invocation.
Object obj = new Foo();
Object s = 1.2;
String type = "Double";
try {
MethodType mt = MethodType.methodType(s.getClass(), s.getClass()).unwrap();
MethodHandle mh = MethodHandles.lookup().bind(obj, "return" + type, mt);
System.out.println(mh.invoke(s));
} catch(Throwable e) {
e.printStackTrace();
}
But note that unlike Reflection, the return type has to be correctly specified for the lookup. I’m assuming the same return type as the parameter type, like in your example.
Can someone please tell me whether there is a way to pass the generic type T to getAPIResponse(...) and build the TypeReference within getAPIResponse method.
I would like to pass Model as a generic type to getAPIResponse and have TypeReference built in within the getAPIResponse method.
TypeReference<APIResponse<Model>> type = new TypeReference<APIResponse<Model>>(){};
APIResponse<Model> response = getAPIResponse(result, type);
I would like to avoid building the TypeReference instance outside the getAPIResponse method, rather would like to create the instance within the getAPIResponse method and pass only the Generic type into the method.
getAPIResponse method
protected final <T> APIResponse<T> getAPIResponse(MvcResult pResult, TypeReference<APIResponse<T>> type) {
APIResponse<T> res = null;
try {
res = new ObjectMapper().readValue(pResult.getResponse().getContentAsString(), type);
}
catch (IOException e) {
Assert.fail(ExceptionUtils.getStackTrace(e));
}
return res;
}
I tried changing to the below
protected final <T> APIResponse<T> getAPIResponse(MvcResult pResult, T t) {
APIResponse<T> res = null;
try {
TypeReference<APIResponse<T>> type = new TypeReference<APIResponse<T>>(){};
res = new ObjectMapper().readValue(pResult.getResponse().getContentAsString(), type);
}
catch (IOException e) {
Assert.fail(ExceptionUtils.getStackTrace(e));
}
return res;
}
But not I am not sure how to call into this method. Lets say I want to return
APIResponse<Bank>
APIResponse<Branch>
APIResponse<List<Employee>>
How do I pass these generic types into my method call in the invoking class?
UPDATE: It doesn't work. JSON is converted to Map instead of APIResponse, .... :(
Try this:
protected final <T> APIResponse<T> getAPIResponse(MvcResult pResult) {
APIResponse<T> res = null;
try {
TypeReference<APIResponse<T>> type = new TypeReference<APIResponse<T>>(){};
res = new ObjectMapper().readValue(pResult.getResponse().getContentAsString(), type);
}
catch (IOException e) {
Assert.fail(ExceptionUtils.getStackTrace(e));
}
return res;
}
And call:
APIResponse<Model> response = getAPIResponse(result);
You don't need give 't' object.
I have classes which aim to contain many attributes of different types. I would want to automatically deep clone all of them rather than writing an instruction for each of them:
class AttributesContainer implements Cloneable {
Type1 a1 = new Type1(...), a2 = new Type1(...);
Type2 b1 = new Type2(...);
...
public AttributesContainer clone() {
AttributesContainer ac = (AttributesContainer) super.clone();
// Regroup that like using a loop
ac.a1 = a1.clone();
ac.a2 = a2.clone();
ac.b1 = b1.clone();
...
return ac;
}
}
I have thought about adding the fields in a table each time but I could not change the reference of the fields:
class ContainerAbstract implements Cloneable {
public <T> T add(T t) {
// adds the reference into a list
return t;
}
public ContainerAbstract clone() {
ContainerAbstract ca = (ContainerAbstract) super.clone();
// copy the attributes
return ca;
}
}
class AttributesContainer extends ContainerAbstract implements Cloneable {
Type1 a1 = add(new Type1(...)), a2 = add(new Type1(...));
Type2 b1 = add(new Type2(...));
...
public AttributesContainer clone() {
AttributesContainer ac = (AttributesContainer) super.clone();
return ac;
}
}
I have also thought that I could return a wrapper in the add() method but it would introduce an extra method get() to call each time I want to access an attribute:
AttributesContainer ac = new AttributesContainer();
ac.get()...;
It there a way to change the fields to there source, like we could achieve that in C using a pointer?
NB: I already checked Copy fields between similar classes in java, How do you make a deep copy of an object in Java? and http://www.java2s.com/Tutorial/Java/0125__Reflection/Returnalistofallfieldswhateveraccessstatusandonwhateversuperclasstheyweredefinedthatcanbefoundonthisclass.htm.
EDIT: One of the reasons I don't use the serialization is that in fact, I have a final property for which I just want a fresh new instance.
I thought about making it transient and then giving it a new object but I can't, since it is final:
class A {
private Double d = new Double(2);
public final transient B b = new B();
public A copy() {
A a = (A) DeepCopy.copy(this);
a.b = new B(); // Error, b is final
return a;
}
}
Always check when articles are written (or questions are asked/answered), otherwise you'll get plenty of misconceptions. The text I quoted in my comment is in the bottom of the page. If you don't see it, use the "Find in page" functionality of your browser.
Serializing and deserializing final fields is not a problem either. You can't write this: a.b = new B(); // Error, b is final, but you don't need to. Serialization is implemented on the JVM level and it can perform plenty of tricks, such as creating objects without calling any constructors.
Finally, the only answer I found without needing to change a final attribute is to change in the class DeepCopy in http://javatechniques.com/blog/faster-deep-copies-of-java-objects/ the ObjectOutputStream method to replace attributes of the class Type with new ones.
ObjectOutputStream out = new ObjectOutputStream(fbos) {
{
enableReplaceObject(true);
}
#Override
protected Object replaceObject(Object arg0) throws IOException {
// TODO Auto-generated method stub
if(arg0 instanceof Type) {
for(Constructor<?> constructor : arg0.getClass().getConstructors()) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if(parameterTypes.length == 0 /* Number of arguments in the constructor of new Type(...) */)
try {
return constructor.newInstance(/* Arguments to the constructor */);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
try {
throw new Exception("The constructor needed to create a new Type was not found.");
} catch(Exception e) {
e.printStackTrace();
}
return null;
} else {
return super.replaceObject(arg0);
}
}
};
out.writeObject(orig);
out.flush();
out.close();
I want tranfers attributes values from a object that came from my Entity manager to a new object.
The return Object is always null
public class ReflectionUtil {
public static Object copyAttributesFromTo(Object a, Object b) throws IllegalArgumentException, IllegalAccessException {
Field[] fieldsFromFirstClass = a.getClass().getDeclaredFields();
Field[] fieldsFromSecondClass = b.getClass().getDeclaredFields();
for (Field currentFieldFromTheFirstClass : fieldsFromFirstClass) {
for (Field currentFieldFromTheSecondClass : fieldsFromSecondClass) {
String nameOfTheFirstField = currentFieldFromTheFirstClass.getName();
String nameOfTheSecondField = currentFieldFromTheSecondClass.getName();
if (!Modifier.isFinal(currentFieldFromTheFirstClass.getModifiers())) {//Dispensa os Final
if (!currentFieldFromTheFirstClass.isAnnotationPresent(Id.class)) {//Não sobescreve campo id
if (nameOfTheFirstField.equals(nameOfTheSecondField)) {
currentFieldFromTheFirstClass.setAccessible(true);
currentFieldFromTheSecondClass.setAccessible(true);
currentFieldFromTheSecondClass.get(b));
currentFieldFromTheFirstClass.set(a, currentFieldFromTheSecondClass.get(b));
}
}
}
}
}
return a;
}
}
In the Facade call I always have to put all the attribute values to new object
public void update(Profile object) {
dao.beginTransaction();
Profile persistedObject = dao.find(object.getId());
persistedObject.setName(object.getName());
dao.commitAndCloseTransaction();
}
So I think to create some like that
public void update(Profile object) {
dao.beginTransaction();
Profile persistedObject = dao.find(object.getId());
ReflectionUtil.copyAttributesFromTo(persistedObject , object);
dao.commitAndCloseTransaction();
}
really miss understood why u are using 2 loop? .. if the classes are same . u dont need to do it .. just do it in 1 loop .. and use fields get for obj which is holding data .. and use set for to set .. here is the more better way .. if the same object is required u can use generics .. and same object type will be required ( request return type )
public static <T> T copyAttributesFromTo(T value, T dataHolder) throws IllegalArgumentException, IllegalAccessException {
if (value == null || dataHolder == null) {
throw new IllegalArgumentException();
}
final Field[] fields = value.getClass().getDeclaredFields();
for (Field field : fields) {
if (!Modifier.isFinal(field.getModifiers())) {
field.setAccessible(true);
field.set(value, field.get(dataHolder));
}
}
return value;
}
The return Object is always null
It is impossible for the return object (i.e. whatever a contains when you return) to be null.
It is easy to see that the code does not change the reference a. There are no assignments to it in the method, so it cannot change.
The other possibility was that you called the method with a null value for a. But if you did that, the first line of the method calls a.getClass() and that will throw an NPE if a is null.
TL;DR - it is impossible.
So what does this mean?
Here are the most likely explanations:
You are mistaken that null is being returned. Perhaps the method is not being called? Perhaps, it is not returning?
Maybe you have misinterpreted the evidence in some other way. It is hard to know without seeing the code ... and the evidence.
Maybe you don't mean that the method is returning Object; i.e. I misunderstood the question. (Your problem description is pretty unambiguous though ...)
I make a change in the code and works to update for me
public static Object copyAttributesFromTo(Object a, Object b) throws IllegalArgumentException, IllegalAccessException {
Field[] fieldsFromFirstClass = a.getClass().getDeclaredFields();
Field[] fieldsFromSecondClass = b.getClass().getDeclaredFields();
//JSFMessageUtil.addMsgLog(JSFMessageUtil.matricula, ReflectionUtil.class.getCanonicalName(), "ReflectionUtil: Aqui");
for (Field currentFieldFromTheFirstClass : fieldsFromFirstClass) {
for (Field currentFieldFromTheSecondClass : fieldsFromSecondClass) {
Object nameOfTheFirstField = currentFieldFromTheFirstClass.getName();
Object nameOfTheSecondField = currentFieldFromTheSecondClass.getName();
if (!Modifier.isFinal(currentFieldFromTheFirstClass.getModifiers())) {//Dispensa os Final
//if (!currentFieldFromTheFirstClass.isAnnotationPresent(Id.class)) {//Não sobescreve campo id
if (nameOfTheFirstField.equals(nameOfTheSecondField)) {
currentFieldFromTheFirstClass.setAccessible(true);
currentFieldFromTheSecondClass.setAccessible(true);
//JSFMessageUtil.addMsgLog(JSFMessageUtil.matricula, ReflectionUtil.class.getCanonicalName(), "ReflectionUtil: " + currentFieldFromTheSecondClass.get(b));
currentFieldFromTheFirstClass.set(a, currentFieldFromTheSecondClass.get(b));
}
//}
}
}
}
return a;
}
The call
public void update(Aluno a) {
try {
Aluno aluno = new Aluno();//(Aluno) em.find(Aluno.class, a.getId());
em.getTransaction().begin();
//aluno.setNome(a.getNome());
ReflectionUtil.copyAttributesFromTo(aluno, a);
em.merge(aluno);
em.getTransaction().commit();
} catch (Exception e) {
System.out.println("Error " + e.getLocalizedMessage());
JOptionPane.showMessageDialog(null, e.getLocalizedMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
} finally {
em.close();
}
}
How to do the following properly in Java? I would like to have a generic routine that can create a list of objects. In this routine I expect the constructor of the class of these objects to support a particular parameter.
To clarify: I would like this routine to create a List<T> from a JSON string. This is part of a larger deserialization code. If I can somehow specify that each supported T implements a constructor that creates T given a JSONObject, then I could write the routine something like this:
interface CreatableFromJSONObject<T> {
T(JSONObject object); // Complains about missing return type.
}
static <T> List<T extends CreatableFromJSONObject> jsonArrayToList(JSONArray array) {
List<T> result = new ArrayList<T>();
for (int i = 0; i < array.length; ++i) {
JSONObject jsonObject = array.getJSONObject(i);
result.add(T(jsonObject)); // If T has one constructor with 1 one argument JSONObject
}
return result;
}
and then with an example class that implements this interface
class SomeClass implements CreatableFromJSONObject {
SomeClass(JSONObject object) throws JSONException {
// implementation here
}
}
I could use the desired method as:
List<SomeClass> list = jsonArrayToList<SomeClass>(someJSONArray);
Now, there are quite some hits on this on StackOverflow, so there I have learned that what I outlined above is not possible because Java does not support specifying a particular constructor in an interface and also not for static methods (which would be an alternative route to the same thing and not possible for the same reason).
So, what is then the best way of achieving this?
My current best attempt is the following:
public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Constructor<T> fromJSONObjectConstructor) {
List<T> result = new ArrayList<T>();
try {
for (int i = 0; i < jsonArray.length(); i++) {
result.add(fromJSONObjectConstructor.newInstance(jsonArray.getJSONObject(i)));
}
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (JSONException e) {
throw new RuntimeException(e);
}
return result;
}
and then to add to each class that should be supported by this method:
public class SomeClass {
public static final Constructor<SomeClass> jsonObjectConstructor;
static {
try {
jsonObjectConstructor = CafellowEntity.class.getConstructor(JSONObject.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
SomeClass(JSONObject object) throws JSONException {
// Implementation here
}
}
which I use as
List<SomeClass> list = jsonArrayToList(myJSONArray, SomeClass.jsonObjectConstructor);
It is the most pretty solution I could come up with apart from not using a generic implementation at all and just put the (in this case) couple of lines of code that is actually doing the work in the routine wherever I need them for a particular class.
Any suggestions? What about the performance of this versus alternative solutions? By not supporting it just like this Java is probably telling me I should not be wanting to do this, but that does not prevent me from wondering about it anyway.
Unless you are doing some kind of unusual deserialization this design is overly-complicated and error prone. Android bundles an excellent JSON parser that can already do this, and do it well. Each type that you are currently defining custom constructors for can be deserialized with a single line of code:
final CustomObj obj = new Gson().fromJson(jsonObj.toString(), CustomObj.class);
Incorporating this into your existing method, you end up with this:
public static <T> List<T> jsonArrayToList(final JSONArray jsonArray,
Class<T> clazz) {
if (jsonArray == null || clazz == null)
return null;
final Gson gson = new Gson();
List<T> result = new ArrayList<T>(jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
try {
result.add(gson.fromJson(jsonArray.getJSONObject(i).toString(),
clazz));
} catch (final JSONException je) {
je.printStackTrace();
return null;
}
}
return result;
}
You may simplify your solution by omitting the constructors instances and using the clazz instances instead. So the signature of jsonArrayToList() would be:
public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Class<T> clazz);
and then calling the constructor by clazz.newInstance();
This would work if you know the type of the class in advance.