I made a switch to Realm last week.
Now, I've got this issue when using reflection:
Normally I'd use reflection to fetch field, which when available I'd use to replace url params in our API url f/e:
blog/{blogId}/comments <- not an actual url but an example.
The code would check if there is a field called blogId, if yes it'll invoke the getter (getBlogId) and replace the value in the path. Now with realm I get a "BlogRealmProxy" which does not contain the properties I was expecting on my RealmObject, it has fields like INDEX_BLOGID (or alike).
Any idea how to use reflection still? I need this to have generic functions available.
Update:
Well I found a way, by doing something quite silly, any better options?:
Class clazz = obj.getClass();
if (clazz.getName().endsWith("Proxy")) {
clazz = clazz.getSuperclass();
}
I'm 100% sure objects will never end with Proxy ;)
Well I found a way, by doing something quite silly, any better options?:
Class clazz = obj.getClass();
if (clazz.getName().endsWith("Proxy")) {
clazz = clazz.getSuperclass();
}
I'm 100% sure objects will never end with Proxy ;) in my app.
Related
C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.
If I have a class like this:
class MyClass
{
public SomeOtherClass MyProperty { get; set; }
public void MyMethod()
{
var aLocalVariable = 12;
}
}
I can use the operator like this:
// with class name:
var s = nameof(MyClass); // s == "MyClass"
// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"
// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"
// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".
This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.
Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?
It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.
See this library: https://github.com/strangeway-org/nameof
The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/
Usage example:
public class NameOfTest {
#Test
public void direct() {
assertEquals("name", $$(Person.class, Person::getName));
}
#Test
public void properties() {
assertEquals("summary", Person.$(Person::getSummary));
}
}
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
You can't.
You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.
The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.
As for local variables, it's not possible at all.
You can't.
If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.
I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof
You can simply use it like this:
Name.of(MyClass.class, MyClass::getProperty)
which would just return the String
"property"
It's also on , so you can add it to your project like this:
<dependency>
<groupId>de.mobiuscode.nameof</groupId>
<artifactId>nameof</artifactId>
<version>1.0</version>
</dependency>
or for Gradle:
implementation 'de.mobiuscode.nameof:nameof:1.0'
I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.
I also created a blog post about the library with more details.
Lombok has an experimental feature #FieldNameConstants
After adding annotation you get inner type Fields with field names.
#FieldNameConstants
class MyClass {
String myProperty;
}
...
String s = MyClass.Fields.myProperty; // s == "myProperty"
I have been trying to develop an application. A bean script will be written as per requirement which in turn will call methods (defined in the application) in various order as per requirement. The application code (apart for bean script) would not be changed.
Also, the application uses external jars which provide large number of methods - of which some are implemented in the application. However, I would like to have the possibility to use the other methods (ones that are not yet implemented) without making changes to application should the requirement arise. For this, I would like to use the Java reflection API. The user should be able to call any method present in the external jars by passing the method name and corresponding parameters (using the the external jar documentation).
I'm a java newbie so I have some code that tries to achieve it (may not be syntactically correct):
public void callExternalJarMethod(String methodName, Class[] methodParameterTypes, Object[] methodParameters)
throws NoSuchMethodException {
String className = "SampleClassName";
Class classObject = Class.forName(className);
Method methodObject;
if (methodParameterTypes.length == 0) {
methodObject = classObject.getMethod(methodName, null);
} else {
methodObject = classObject.getMethod(methodName, methodParameterTypes);
}
// Not handling calling of static methods in which case "null" would be passed instead of methodObject to the invoke method
Object returnValue = methodObject.invoke(methodObject, methodParameters);
}
I'm trying to find a way I can get the Class[] methodParameterTypes, and Object[] methodParameters populated with the relevant values. I would have the parameter types and parameter values as string. Also, any pointers towards useful utils would be appreciated.
Thanks in advance.
You are not passing an instance of SampleClassName to the Method.invoke() call here...
Object returnValue = methodObject.invoke(methodObject, methodParameters);
If the method you are going to invoke is static, you can do this...
Object returnValue = methodObject.invoke(null, methodParameters);
Otherwise (non-static), you need to create an instance of SampleClassName to execute the method on.
If the class does not need any constructor arguments, you could use...
Object returnValue = methodObject.invoke(classObject.newInstance(), methodParameters);
(Obviously there will be a load of Exceptions that you need to handle by doing "newInstance" and "invoke"...)
I would like to access the usual reflection properties of a specific method without relying on Strings.
Is there any way to get from the method-Identifier to its reflection properties, like parameter types?
void run() {
java.lang.reflect.Method m = myMethod.getMethod(); // how?
Class<?>[] argClasses = m.getParameterTypes();
}
int myMethod(String arg) {
// ...
}
The piece myMethod.getMethod() is not valid. It is my way of saying "get from the method-identifier to the java.lang.reflect.Method object".
The string-way I do not want to use would be similar to m = getClass().getDeclaredMethod("myMethod", ...)
I use myMethod like a regular identifier and not as a String, i.e. "myMethod". I think this would be beneficial for refactoring, where someone renames myMethod to hisMethod -- the relation via the String-name would break, where the relation via the identifier would be refactored as well.
In java methods aren't first class citizens, so there is no solutions in Java for this problem.
Yet I had a similar problem and forged a small tool named picklock for this purpose.
Is there any way to read and print the object attribute dynamically(Java) ? for example if I have following object
public class A{
int age ;
String name;
float income;
}
public class B{
int age;
String name;
}
public class mainA{
A obj1 = new A();
method(A);
method(B);
}
the output should be like
While running method(A):
Attribute of Object are age,name,income;
While executing method(B):
Attribute of Objects are age,name;
My question is I can pass various object in method(), is there any way I can access the attribute of the differnt object in general.
You want to use The Reflection API. Specifically, take a look at discovering class members.
You could do something like the following:
public void showFields(Object o) {
Class<?> clazz = o.getClass();
for(Field field : clazz.getDeclaredFields()) {
//you can also use .toGenericString() instead of .getName(). This will
//give you the type information as well.
System.out.println(field.getName());
}
}
I just wanted to add a cautionary note that you normally don't need to do anything like this and for most things you probably shouldn't. Reflection can make the code hard to maintain and read. Of course there are specific cases when you would want to use Reflection, but those relatively rare.
Using org.apache.commons.beanutils.PropertyUtils we can do this. If the proper getters and setters are defined for the bean we can also dynamically set the value:
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;
public class PropertyDescriptorTest {
public static void main(String[] args) {
// Declaring and setting values on the object
AnyObject anObject = new AnyObject();
anObject.setIntProperty(1);
anObject.setLongProperty(234L);
anObject.setStrProperty("string value");
// Getting the PropertyDescriptors for the object
PropertyDescriptor[] objDescriptors = PropertyUtils.getPropertyDescriptors(anObject);
// Iterating through each of the PropertyDescriptors
for (PropertyDescriptor objDescriptor : objDescriptors) {
try {
String propertyName = objDescriptor.getName();
Object propType = PropertyUtils.getPropertyType(anObject, propertyName);
Object propValue = PropertyUtils.getProperty(anObject, propertyName);
// Printing the details
System.out.println("Property="+propertyName+", Type="+propType+", Value="+propValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
To set the value of a particular property:
// Here we have to make sure the value is
// of the same type as propertyName
PropertyUtils.setProperty(anObject, propertyName, value);
Output will be:
Property=class, Type=class java.lang.Class, Value=class genericTester.AnyObject
Property=intProperty, Type=int, Value=1
Property=longProperty, Type=class java.lang.Long, Value=234
Property=strProperty, Type=class java.lang.String, Value=string value
You can use reflection to get every field from your object (if security configuration allows you).
If you need it not for the sake of self-education, then it may be worth using ReflectionUtils from Apache Commons.
You can use reflection, but the API is not very nice to use. But what you are trying to do is not at all object-oriented. The A and B should have method "print yourself" which would output their values (you should specify the method in superclass/interface to call the method using polymorphism).
I think I would consider a different approach.
If you really want to treat these like data is there any reason they couldn't be hashtables (Do they have associated code)?
Reflection will do it but it's a last resort--you should always seriously consider different approaches before dropping to reflection.
Cases where you must access variables like that exist--like database mapping (Hibernate) and injection (Spring). You might want to consider if a packaged solution like that fits your need so that future programmers can understand what you did without learning everything about your specific solution.
Also, Spring injection can do things that might fit your needs.
Also also if you are going to use reflection, seriously consider annotations so that you aren't tying your functionality to what should be simple arbitrary attribute names.
In java i have a bean object(type unknown) i want to put the values of members of that bean into one HashMap with class members as key.Without using reflection can i do that if so how ? otherwise tell me a good way to do it using reflection
beanObject = { name="raja",age="20"} to haspMapObj = {name="raja",age="20"}
As peoples you said i tried introspector:
thank you for your answer and advise friends.
Class myClass =myObj.getClass();
info = Introspector.getBeanInfo(myClass);
for ( PropertyDescriptor pd : info.getPropertyDescriptors() ){
String name = pd.getName();
System.out.println("*************"+name+","+ pd.getValue(name));
}
but the above is print only the name the value's is coming as null. bcoz we are passing only the class type not the object reference. how do we do to get the value?
You can use the Introspector to get all the fields of a bean and their values. (This wraps reflection)
I think you can't do it without reflection. With reflection you can do something like this:
Map<String, Field> map = new HashMap<String, Field>();
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
map.put(field.getName(), field);
}
I do not see any possibility without using reflection at least indirectly via frameworks.
If you take a look at the Apache Commons Beanutils you might find some helpful methods:
http://commons.apache.org/beanutils/
More specified:
http://commons.apache.org/beanutils/v1.8.3/apidocs/org/apache/commons/beanutils/BeanMap.html
Best regards!
You can use introspection, which is based on reflection:
http://download.oracle.com/javase/6/docs/api/java/beans/Introspector.html
But what exactly do want to do in the end? Maybe there is a better way...
To get the value from a PropertyDescriptor pd:
Object value = pd.getReadMethod().invoke(myObj, new Object[]{});
Note, some time ago I wrote a utility class, which you might find useful:
http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/beans/BeanIntrospector.html