java reflection question - java

I'm trying to solve the following issue in reflection. I've a POJO which kind of acts as a metadata for the method signature in TestResponse class. TestResponse has a setDate() methid which takes a Date parameter. I'm trying to make this is a generic code which can accept any method and its signature to set in the response. What I'm not able to figure out is how to set the parameter Class while calling getMethod() based on the input. The input tells me to set the parameter as Date, but not sure how to achiever that.
Here's my sample code. Ofcourse, the mdi.modifier.getClass() is wrong since it'll get String.class instead of Date.class.
TestResponse response = new TestResponse();
Object val = "test";
MDIBase mdi = new MDIBase("setDate", "Date");
Method m = response.getClass().getMethod(mdi.method, mdi.modifier.getClass());
m.invoke(response, new Object[] { val });
Here's MDIBase
public class MDIBase {
public String method;
public String modifier;
public MDIBase(String method, String modifier){
this.method = method;
this.modifier = modifier;
}
Any pointers will be highly appreciated.
Thanks

I'm not sure I fully understand you, but if I do, you want to be able to pass in a class name for the parameter?
In order to do that, instead of passing in "Date" pass in "java.util.Date" (this is known as the fully qualified class name) and then instead of getClass call
response.getClass().getMethod(mdi.method, Class.forName(mdi.modifier));
That will dynamically load the class that has the fully qualified name you supplied.
Is that what you're looking for? If not, give me some more information and I'll take another stab at it.

Related

Casting a String to another type as a parameter of a method in Java reflection

I am trying to pass a value to a method by means of reflection in Java.
Namely, say we have string
String value = (some string representation of a value of type Type);
Say, we have a class with no-args-contructor, a single field int field and a single method, a setter method setTheField:
public class SomeClass{
private SomeType field;
SomeClass(){};
public void setTheField(SomeType parameter){
this.field = parameter
}
}
where SomeType of field may be primitive, wrapper or LocalDate / LocalDateTime.
If I take the setter (say):
Method setter = SomeClass.getClass().getDeclaredMethods()[0];
and then find out its parameters (say):
parametersList = Arrays.stream(setter.getParameters())
.collect(Collectors.toList());
Then if check if the setter requires a single parameter:
if (parametersList.size() != 1) {
throw new IllegalArgumentException("Setter named = " +
setter.getName() +
" is not a single parameter setter!");
}
What I really want to do then, is to pass string to 'setter' on some object SomeClass object = new SomeClass(); as setter.invoke(object, value); and I need somehow to cats String value to SomeType but I can not figure out how to do it uniformly.
Though, it seems a standard situation to appear and I hope someone more enlightened then me in Java can quickly figure out what to do.
Any suggestions are welcome.
Addendum:
I elaborate some more here.
The task I am trying to do is the following. Suppose I have an annotations #Column{String name} targeted to methods (or fields). Suppose I also have some domain class SomeClass with some setters (fields) annotated as #Column. I have to read from CSV top row with column names (headers to link data to the annotation's name), then I have to return a list of objects of my domain class SomeClass. This is the reason I am using reflection and I see no other way around.
Without more context this looks like a design problem. Why go through all the work to grab a setter by reflection and given a String, get a value compatible with the setter argument's type? If there's no other way around this problem, it is not possible to just cast a String to some other type. One possibility is making a factory class.
Assumption: the setter's argument type is some class called MyType.
class ArgumentFactory {
MyType valueFor(String in) {
// based on the string's value, put the conversion logic here
if (in == null || in.isEmpty()) {
return new MyType();
}
// add other cases as necessary ...
}
}
Then you have
ArgumentFactory factory = new ArgumentFactory();
// ...
String value = "qwerty";
setter.invoke(object, argumentFactory.valueFor(value));

Class registration using reflection

I'm learning about Factory Pattern and I am using THIS article as a source. In it, there is this piece of code:
class ProductFactory {
private HashMap m_RegisteredProducts = new HashMap();
public void registerProduct (String productID, Class productClass) {
m_RegisteredProducts.put(productID, productClass);
}
public Product createProduct(String productID) {
Class productClass = (Class)m_RegisteredProducts.get(productID);
Constructor productConstructor = cClass.getDeclaredConstructor(new Class[] { String.class });
return (Product)productConstructor.newInstance(new Object[] { });
}
}
I'm having a hard time figuring out how createProduct() method works. When I'm trying to use this code I get Non-static method `getDeclaredConstructor(java.lang.Class<?>...)' cannot be referenced from a static context error. productClass variable is declared but never used so there is clearly something wrong with the code but I can't figure what exactly. I checked similar questions on SO but don't know how to repurpose them for this case. Reflection is a really confusing subject for me.
My questions:
What is wrong with this code?
Why it is passing new Class[] { String.class } in getDeclaredConstrutor() method and what does it mean?
Why is it passing Object array in newInstance() instead of just single object?
Question 1
There are several things wrong about this code.
It just does not compile because cClass member is missing. Logically, It should be productClass.getDeclaredConstructor instead.
Raw HashMap is used instead of generically typed Map<String, Class<? extends Product>>. Also raw typing for Class and Constructor.
The naming m_RegisteredProducts does not respect Java naming conventions.
Question 2
new Class[] { String.class } arg aims to retrieve the constructor with a single String arg, for example public Product(String id).
It could have been retrieved with just
productClass.getDeclaredConstructor(String.class);
because it is not mandatory to create arrays for varargs.
Question 3
This array arg just looks like a blunder. The constructor instance is retrieved for one with String arg, but it is passing something else to instantiate it. So inevitably there will be an exception thrown.
Conclusion
There are too many wrong or inaccurate things in this example and probably in the article itself. I'd recommend choosing another one.

How does getDeclaredMethod work in java

I'm not sure how "getDeclaredMethod" works in java, can some one explain how to get the value from the method, this is what i have..
I want to get this value (body_number), which is in the AIBody Class.
public int getBody_number() {
return body_number;
}
And in the same class i have this
Method m = body_A.getUserData().getClass().getDeclaredMethod("getBody_number", null);
How would i get the "body_number" value from m?
ps getUserData is a class of the object that i want to get the method answer out of
Any help would be great.
Adam
Since m is an instance method of whatever object is returned by body_A.getUserData() and it takes no arguments, you'd do something like this:
Method m = body_A.getUserData().getClass().getDeclaredMethod(
"getBody_number", null
);
int val = (Integer) m.invoke(body_A.getUserData());
(You'll have to wrap it in a try/catch or declare the appropriate throws in the method in which this code executes.)
Of course, once you have the Method object, you are not limited to invoking it for the object returned by body_A.getUserData(); you can pass it any instance of AIBody.
Reference: Method.invoke() doc
However, I have to agree with what Bhaskar wrote: why are you using reflection for this? You can simply call:
int val = body_A.getUserData().getBody_number();
You get back an instance of java.lang.reflect.Method, on which you use the invoke method
int val = ((Integer)m.invoke(body_A.getUserData())).intValue()
You may want to consider why you are using reflection in this case and not just
body_A.getUserData().getBody_number()

call get methods for different classes behind one another

I have a class with name "ConstituentSet". it has one method namely "getNucleusInConstSet()" which the output will be from "Proposition" class . The new Class "Proposition" have another method namely "getProperty()". I want to know what is the Propertry of my "Proposition Nucleus" in class "ConstituentSet". but i do not know how can i do that.
I wrote as follow but It does not work. (ConstituentSet.getNucleusInConstSet()).getProperty())
public class ConstituentSet{
// Constructor
private Proposition nucleusInConstSet;
public Proposition getNucleusInConstSet() {
return nucleusInConstSet;
}
}
public class Proposition{
//Constructor
private Property property;
public Property getProperty() {
return this.type;
}
}
You have:
(ConstituentSet.getNucleusInConstSet()).getProperty()
But you need to call an instance of ConstituentSet
e.g.
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Note that this idiom (chained method calls) can be a pain. If one of your methods returns null, it's difficult to understand which one it is (without using a debugger). Note also that invocations of the form a().b().c().d() are a subtle form of broken encapsulation (a reveals that it has a b, that reveals it has a c etc.)
if you type ((ConstituentSet.getNucleusInConstSet()).getProperty()) you are attempting to call a static method of ConstituentSet.
You need to instantiate it and then call on that object.
ConstituentSet anInstanceOf = new ConstituentSet();
anInstanceOf.getNucleusInConstSet()).getProperty());
This won't work:
ConstituentSet.getNucleusInConstSet().getProperty();
Because the getNucleusInConstSet() method is not static. You have to use an instance of ConstituentSet, something like this:
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Of course, you have to make sure that nucleusInConstSet is not null, or you'll get a NullPointerException. Initialize its value in ConstituentSet's constructor or set it using setNucleusInConstSet().
Alternatively, you could make getNucleusInConstSet() static, but I don't think that's the right thing to do in this case (but we don't have enough information about the problem to say so).

Setting a Variable in another class results in an error

What I am trying to do is set a value in a variable contained within another class.
this is how I am currently trying to achieve it.
BookingUI Class
private void setCarRegNo()
{
aBooking.setCarRegNo();
}
Booking class
public void setCarRegNo(String regNo)
{
carRegNo = regNo;
}
Yet I keep getting an error saying 'setCarRegNo (java.lang.String) in booking cannot be applied to ()
What is it I am doing wrong? Many thanks
You need to pass a String into the setCarRegNo(String ) of Booking class. The method signature declares that it requires a String argument, and your compiler will complain if you dont supply one.
You have to pass a string into the setCarRegNo() function.
Like this: setCarRegNo("Some string");
In your Booking Class, setCarRegNo takes a single parameter of type String.
When you call it from BookingUI, you are not passing in any parameters.
You need to change BookingUI to something like:
private void setCarRegNo()
{
aBooking.setCarRegNo("CarRegNo");
}
you need to pass a string to your setter. change
aBooking.setCarRegNo();
to
aBooking.setCarRegNo("the registration number');
as a note, you should fully spell out the words of the variables.

Categories

Resources