Correct way of achieving this.class using reflection - java

Suppose I have a class Foo in package my.package which contains some static fields.
I want to use reflection to get the values of those static fields.
I know I can write my.package.Foo.class.getDeclaredField(... but this is unsatisfactory as I'm hardcoding the class and package names.
I'd like to use this.class.getDeclaredField(... but this is invalid in Java even if called from within a non-static member function.
Is there a way?

Every class inherits the instance method Object#getClass(). Invoke that to get your instance's corresponding Class object.
I don't know why you would do this inside Foo as Foo already knows its static fields and you'd have access to them at compile time directly.

Non-statically, you can use this.getClass() to get the current class, as #sotirios-delimanolis mentioned.
Statically, you can do this, though it is a bit ugly:
public static Class<?> getCurrentClassStatic() {
try {
return Class.forName(new Throwable().getStackTrace()[0].getClassName());
} catch (ClassNotFoundException e) {
return null; //Shouldn't happen...
}
}

Related

How to acces JavaFX fields via Annotation?

What I'm trying to do:
I have a Java program in which I use JavaFX. I created a fxml file in which I created JavaFx controllers, which I then declared in the AddEmployeeOrderController class. I would like to transfer these created controller fields to a POJO. Since I think it is very time-consuming and leads to a lot of careless mistakes, I wanted to automate this process more. My idea was to make an annotation for each declared JavaFX controller field so that, for example, all annotated fields are gonna be retrieved automatically at for example a push of a button in another method. So you can understand it that way instead of writing everything by hand yourself, e.g.:
EmployeeDto employeeDto = new EmployeeDto(textfield.getText(), textfield2.getText()..);
I first formed the AddEmployeeOrderController and declared some JavaFX field and added an annotation. Again in the AddEmployeeOrderController class I tried to access the annotated field.
Then, logically, I would have to cast to cast the java.lang.reflect.Field to a JavaFX TextField, but that is obviously not possible. It throws only IllegalArgumentException errors, and of course because you can't cast a java.lang.reflect.Field to a JavaFX TextField.
Is there a way in which my idea can be achieved with the help of annotation, or am I forced to write everything by hand and generate so-called boilerplate code.
public class AddEmployeeOrderController implements Initializale {
#FXML
#MyAnno
public TextField orderDateFromTextField;
public void atPushButton() {
for (Field field : AddEmployeeOrderController.class.getDeclaredFields()) {
if (field.isAnnotationPresent(MyAnno.class)) {
if (((Field) object).getType().getCanonicalName()
.contains("TextField")) {
TextField textField = (TextField) field.get(this);
textField.getText();
}
}
}
}
}
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnno {
}
You have not provided sufficient (relevant) code to understand what you are actually doing. However, we can deduce the following:
The Field class you are using is java.lang.reflect.Field.
According to the javadoc, the Field.get(Object) should be called with a reference to an instance ... or null. If an instance is provided, then it needs to be an instance the class that declares the field, or a subclass of that class.
If Field.get is called with a parameter that is NOT of the required class, IllegalArgumentException is thrown.
So ... if what you have told us and shown us is correct ... this is not the correct object to be passing to Field.get on that Field object.
You are saying that the field reflection code you are showing us is in the AddEmployeeController class. That means that this would be a AddEmployeeController instance. But the Field instances you are iterating are for the fields declared by the class AddEmployeeOrderController. So, you should be calling get with a (non-null) value that refers to an AddEmployeeOrderController instance. (Or maybe you should be iterating the declared fields of AddEmployeeController. Without more context it is difficult to say what the correct fix is.)
If we strip away all of the dynamic / reflective stuff, what your code is doing is analogous to this non-reflective code:
public class AddEmployeeOrderController {
public TextField someField;
}
public class AddEmployeeController {
public void someMethod() {
TextField t = (TextField)(this.someField);
}
}
It won't compile because AddEmployeeController doesn't have a field called someField.
What you actually need to do is the analog of this:
public class AddEmployeeController {
public void someMethod(AddEmployeeOrderController aeoc) {
TextField t = (TextField)(aeoc.someField);
}
}
Just to clarify, the problem is not coming from the typecast in
(TextField) field.get(this);
If the typecast was failing, then the exception would be a ClassCastException. The exception you are seeing comes from the get call!
And the problem is not due to annotations.
FOLLOW-UP
I have taken your (attempted) MRE, factored out the JavaFX stuff, and turned it into working code. My version shows how to extract a field value reflectively by matching the field's type and an annotation.
package test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnno {
}
// End of MyAnno
package test;
import java.lang.reflect.Field;
public class MyTest {
#MyAnno
public String someField = "Hi Mom";
public void doIt() throws Exception {
for (Field field : this.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(MyAnno.class)) {
if (field.getType().getCanonicalName().equals("java.lang.String")) {
String value = (String) field.get(this);
System.out.println(value);
}
}
}
}
public static void main(String[] args) throws Exception {
new MyTest().doIt();
}
}
Note that this is REAL code. It compiles, runs and ... works. Try it. If you change String to (say) TextField, you can adapt it to your problem. (The actual type of the field is almost entirely irrelevant to the core problem. As you can see.)
(One thing that could be improved and simplified is that the type test should use Class.equals rather than testing the name of the class. It is cleaner and more reliable.)
One of your concerns was (I think) that you would need a lot of boilerplate code to make this work for your problem. I don't think that is the case:
If I declare an abstract superclass for MyTest and put the implementation of doIt() there ... it should just work. Notice that doIt() uses this.getClass() to get the current object's class.
It would also work if doIt() was in an unrelated class, provided that the method had an argument for passing the target Object.
It would even be possible to parameterize this on the type of the field. Or look for fields that are subtypes of a given type. And so on. (Hint: you would need to pass the type as a Class object.)
I said "(attempted) MRE" for a reason. In fact, your code doesn't compile. Indeed, you have a variable (object) which is not declared, and whose intended type and purpose is hard to fathom. I have assumed that it was a mistake, and guessed that your intention was to use field there. But I should not have to guess!
A real MRE needs to be complete and compilable (unless your problem is how to get it to compile). Ideally it should also be runnable, and running the MRE should reproduce the problem you are asking about.
The point is that we (people trying to help you) need to be sure that we understand what your problem is. That is the purpose of the MRE.

Java calling method from generic class

Is something like that possible.
List<?> myList = getMyList();
class cls = class.forname("com.lab.myClass");
cls = myList.get(0);
cls.getValue();
Create an Instance with the fully-qualified name of a class and use their declared Methods?
No, if you call Class.forName, at compile time you know nothing about the returned Class instance. You don't even know that it represents a class; it might be an interface for example. In particular, if it is a class and you create an instance of it, you cannot call any methods of it except those which are already defined in Object because, at compile time, the compiler cannot check whether these methods exist.
The are two solutions:
First, you can use reflection to find out about the methods the class has, and to call these methods. This is very cumbersome.
Second, if you use Class.forName to dynamically load classes at runtime, often you know something about the classes you load. For example, you might know that the class implements a certain interface. Then you can cast the result of newInstance to this interface and then call the methods defined in this interface directly.
For example:
// in file Plugin.java
interface Plugin {
void doSomething();
}
// in file Main.java
public class Main {
...
void runPlugin() {
try {
Class<?> pluginClass = Class.forName("pkg.name.MyPlugin");
Plugin plugin = (Plugin) pluginClass.newInstance();
plugin.doSomething();
}
catch (...) {
// catch the necessary exceptions
}
}
}

Access private method having parameter with private access specifier

I am writing a Junit for a method with multiple parameters and having private access specifier. I am using Java reflection to achieve this. However, one of the parameter for this private method is private class. I am doing below:
ClassHavingPrivateMethod object = new ClassHavingPrivateMethod();
object.getClass().getDeclaredMethod(PRIVATE_METHOD_NAME, Param1.class, <This parameter is a private class Inside ClassHavingPrivateMethod>)
How can I proceed?
EDIT
I agree on the point that I should not write a test case for a private method with reflection and it should always be accessed through a wrapper public method. However, is there any way to achieve the above objective through reflection. Even though, I am not going to write my test case through reflection but I am eager to know about it.
Any help is really appreciated.
One of the way you can try by changing the access from private to default. By changing the access level to default the method can be accessed only from the same package (still restricted access) on the other hand since your test class and class under test will be under same package , the test class can call that method directly, without doing any trick.
Example :
package com.test;
class SomeClass {
String defaultMethod(){
...
}
}
package com.test;
class SomeClassTest {
public void testDefaultMethod(){
SomeClass testObject = new SomeClass();
testObject.defaultMethod();
}
}
Hope it will help.

Doing an API, constructor for system private use only and another official, javadoc'ed and public to use. Advise on fix / pattern approach

I guess this is a bad pattern, whats the best approach to fix it?
I mean I would like everybody using a constructor with 2 arguments,but I need to leave default constructor because its implementing a listener which classloads it without args. I would like to hide default constructor to anyone else but the listener handler which uses it, and make the other the unique point to instantiate.
Is there any kind of annotation? any privacy modifier for certain classes (system caller one is not in the same package)?
This seems fine to me. You would do the same thing if you want to instantiate a class differently during unit testing.
Oh, I see you need a constructor that has more access than protected but less than public. Unfortunately that's not possible.
You could put both your class MyClass and the listener MyListener that needs to use the empty constructor in the same package. Then, set the access of the empty constructor to package-level:
package com.stackoverflow.foo;
public class MyClass {
MyClass () { // package-private (no explicit access modifier)
}
public MyClass(int a, int b) { // public
}
}
package com.stackoverflow.foo;
public class MyListener {
private MyClass ref = new MyClass(); // MyListener is on the same package as MyClass, so this is valid
}
This way, you ensure that only classes that are on the same package as MyClass can use the default constructor.

how to read object attribute dynamically in java?

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.

Categories

Resources