help requested understanding Java Reflection --> Android ParcelableContainer - java

I'm, playing with the Android framework and try to get my mind deeper into Java. For This I read about Javas Generics and the Reflection API, while I'm not understanding it really.
Because I'm a lazy Dev ;) I tried to write an 'Parcelable-Container' in which I can put ANY Object I wish to get it Parcelable without the need to implement this for every Object again using methods of Java Reflection.
I write a test method like these:
public <T> void writeClassInformations(T t){
Class c = t.getClass();
System.out.println("DeclaredFields: ");
for (Field f : c.getDeclaredFields()){
System.out.println(f.toGenericString());
}
System.out.println("Fields: ");
for (Field f: c.getFields()){
System.out.println(f.toGenericString());
}
}
How can I get every member even if they are Objects or private Superclass members?
And another Question: The output is like this:
public int hello.test.Testclass.myID
how I get the value of 'myID'?
ADD:
I'm running in serious problems now. The Interface of Parcelable.Creator forces me to write a statement like: public static final Parcelable.Creator CREATOR =
new Parcelable.Creator<ParcelableBox<?>>()
Can I use ? somehow? Normally I use a constructor like ParcelableBox(E object). While it seems to me that I can't use Object methods on ? I even cannot pass it into a class variable like
public ParcelableBox<?> createFromParcel(Parcel source){
...
return new ParcelableBox<?>();
}
or ? myClass to use Reflection on it. Is this the end of javas reflection power? How can I get Class of ?

Reflection should be used sparingly, or not at all if it can be avoided, and especially not as a way to hack around good design principles. That being said, it can also be useful in certain situations ...
getDeclaredFields can return all types of fields while getFields only returns fields marked public.
The reason your test returns the same thing is that you're using getDeclaredFields in both statements.
how I get the value of 'myID'
You can only do that by operating on an instance of a class. E.g.,
T t = ...
Field field = t.getClass().getDeclaredField("myID");
field.setAccessible(true);
String value = (String) field.get(t);

Related

Is there any way to instantiate a Class<C<A,B>> object in java?

I'm trying to use Hibernate and TypedQuery in java.
The method I'm trying to call has a signature of
<T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass)
I want to call it like bellow but with null replaced by a real instance.
Class<Tuple2<Date,String>> cls=null;
List<Tuple2<Date,String>> books=em.createQuery("select new io.vavr.Tuple2(date,title) from Book where publicationdate > '2008-01-01'",cls).getResultList();
the above code compiles but obviously chrashes with a null pointer exception.
If my understanding of erasure is correct this would work as long as I get an instance of the Class object as all generic type information would be lost at runtime anyway.
Is there any way I can get an instance of Class that i can assign to the variable cls so that this code will work?
Based on #Thomas comments on the first post I came upp with the following.
While it dies not seems to be a way to instantiate such a Class object a relativly readable solution can be achived with subclassing.
In the class where the code resides add outside any function
public static class DateStringPair extends Pair<Date,String>{
public DateStringPair(Date d,String s){super(d,s);}
}
And then the call becomes
List<DateStringPair> books=em.createQuery(
"select new com.example.ConnectionAndQueryTest$DateStringPair(publicationDate,title) from Book where publicationDate > '2008-01-01'"
,DateStringPair.class).getResultList( );
this have the limitation that the Pair class must not be final.
While not as flexible as full generics support in the query readability of the query can be maintained without that much fuss.

Efficiency of accessing local variable vs field?

I read that you should avoid referencing a field too often in a method and instead just do it once, assigning it to a local variable, e.g.:
public static void doSomething() {
final Map<String, Integer> myMap = this.theMap;
//do some processing with myMap
}
The reason being efficiency, it just takes longer to access the field every time. Is that something you should worry about?
This is absolutely wrong.
It makes no difference at all how the variable is accessed (locally or using the class' member). In the end both fields will just contain a reference to the very same location in the memory without any impact to performance. Even when using a getter for your class' field it will make no difference as the JIT compiler will inline the method call once it noticed that this might improve performance.
Optimisationwise: it does nothing really. Any benefit if any would also be provided by an optimizer.
Only benefit is for you, the coder, by being able to name it differently so you know it's purpose in the method better.
public function test() {
Produce harvestedFruits = this.produce;
for(Produce fruit : harvestedFruits ) {
if(fruit.isRotten()) {
harvestFruits.remove(fruit);
}
}
}
And even then, I'd advice using getter and setter methods, so extended functions can do their own thing and testing becomes easier, and with documentation you provide nice highlights when hovering over the method in an relatively advanced IDE
Produce fruit = this.getProduce();

How do I access a Java static member from Scala with reflection?

I have an autogenerated Java class that I'm using in a Scala application. Something like:
public class Model123123 extends GenModel {
public int nclasses() { return 4; }
// Names of columns used by model.
public static final String[] NAMES = NamesHolder_Model123123.VALUES;
I can create instances like this
val model = Class
.forName("Model123123")
.newInstance()
.asInstanceOf[GenModel]
I'd like to access the static members of this Java class. I can do it directly, like this:
Model123123.NAMES
but don't understand how to do it via reflection. I've tried:
scala> Class.forName("Model123123").NAMES
<console>:10: error: value NAMES is not a member of Class[?0]
Class.forName(model_name).NAMES
and
scala> model.getClass.NAMES
<console>:11: error: value NAMES is not a member of Class[?0]
model.getClass.NAMES
I don't know a ton about Java or scala reflection, so I'm a bit lost. I'm trying to do this via reflection as I will have many classes that subclass the same parent class and I'd like to change the class dynamically at runtime.
Thanks
it should be possible like this:
val clazz = Class.forName("Model123123")
val field = clazz.getDeclaredField("NAMES")
val value = field.get(null).asInstanceOf[Array[String]]
We get the class and ask for field in a same way as we would do for non-static field. Once we have the field we can get the value of it by calling get method. The null argument means that we are not passing it any instance from which it should get the value ( since it's static member). At last we have to manually cast the type to the type we're expecting, because type information is lost at this time.
If you need to update the value of static field you can do it as
field.set(null, Array[String]("name1", "name2"))
We again pass null since we don't need to set it on some specific instance since it's class member.
It's basically just java reflection used in the scala language. Another approach is to use scala mirrors - http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html
In your case, the best way is to cast model instance to a common interface hex.genmodel.GenModel as you did, then you can easily call getNames method to access names.
There is no need to use reflection to access static members.

Is it possible to get static property by class name?

For example, I need to get static property from one of my own classes Class1 or Class2 (property name is same for both classes) depend user action. I have only class name in String variable. How to get this property?
Certainly I can to do this:
InfoClass ic;
if(className.equals("Class1")) {
ic=Class1.prop;
} else if(className.equals("Class2")) {
ic=Class2.prop;
}
But that is not so fine solution, I think... Is there another way to implement this?
You can do this, but as mentioned in the comments it's even less neat than your current solution.
Class clazz = Class.forName(qualifiedClassName);
Field field = clazz.getDeclaredField("prop");
ic = (InfoClass)field.get(null);
It's quite likely that there's a different way to do whatever it is you're doing in your app, which doesn't require reflection or a long list of conditionals; but I don't know enough about your problem to know what that is.
Use reflection:
Class.forName("mypackage.MyClass").getDeclaredField("field").get(null);

Using reflection to get the initialization value of a field

public class MyClass {
private String s = "foo";
}
Is it possible to get "foo" using reflection without having to instantiate a new MyClass?
Field field = MyClass.class.getDeclaredField("s");
// -- ideally: --
// Object initializationValue = field.getInitializationValue();
// assert initializationValue.equals("foo");
Initialization statements like you have shown are actually moved into the constructor of the class, by the compiler. You need to actually instantiate a class in order for them to be executed. This is all behind the scenes of course. But in answer to your question, no, you cannot, not with reflection anyway.
But you could possibly determine those field values with static analysis tools like Soot, etc.
It is not possible without "cheating".
One cheat might be to write (or generate) a class that creates a new MyClass instance, and uses reflection to dig out the value you want and write it to stdout. Then you launch a child JVM to run that class, and read it in the current on.
Net result - you gotten the value without instantiating MyClass in the current JVM.
Another cheat would be to use a bytecode library to read the bytecodes from the MyClass ".class" file and simulate the execution of the MyClass initializer in the context of the current JVM.
ClassGraph can do this:
String clsName = "com.xyz.MyClass";
String s;
try (ScanResult scanResult =
new ClassGraph().whitelistClasses(clsName).enableFieldInfo().scan()) {
s = (String) scanResult.getClassInfo(clsName).getFieldInfo("s")
.getConstantInitializerValue();
}
N.B. this works only for constant initializer values (values that can be computed without object instantiation, with the exception of String), assigned to static final fields. The compiler can produce a constant at compiletime for simple arithmetic and simple string concatenation.
(disclaimer, I am the author of ClassGraph)
If you don't mind loading the class, you can also simply use reflection to access static fields: https://stackoverflow.com/a/4076792/3950982

Categories