I have a class that is going to be passed into a function and it will be defined as follows:
class ayy{
String blah;
Class a;
Class b;
}
I want to be able to invoke the getSimpleName() method on the classes a and b. Currently I am doing it as follows:
Class c = (Class)argument; // Where argument is the "ayy" class
c.getField("a").getSimpleName();
But this gives me an error saying "getSimpleName()" is not defined for type field.
You cannot call a method directly on an object that results from reflection, such as you're doing with Field, as if it were a reference variable of the desired type.
Instead, you'll need to call getDeclaredField, because getField only gets public fields. Also, you'll need to get() the value of the Field, passing in an instance of the ayy class, which will return the value of the Field. Then you'll need to cast it to a Class, because get() returns an Object. Then you can call getSimpleName().
Class<?> classOfA = (Class<?>) c.getDeclaredField("a").get(anAyy);
String simpleName = classOfA.getSimpleName();
You'll also need to catch the various reflection-related exceptions that may be thrown.
Related
I have two classes in java. I am calling a method of 2nd class from 1st class when the 2nd class name is stored in a string variable.
I tried the below code.It creates the class.
String adapterClass = "com.appzillon.server.impl.ViewAccDtlsAdapterImpl";
Class className = Class.forName(adapterClass);
After that how to call the method.Method name is getInfo with a string type paramater.
Method method = className.getDeclaredMethod("getInfo", String.class);
method.invoke(instance, "your parameter");
Where instance is either:
Object instance = null;
if the method is static. Or:
Object instance = className.getDeclaredConstructor().newInstance();
If the method is a member method
For scenarios like these, you can very well use Java Reflection APIs.
Class classInstance = Class.forName(<your class name>);
Methoed methodHandle = classInstance.getMethod(<methodName>,<arguments classes>);
Object returnValue = methodHandle.invoke(null, "parameter-value1");
Note : The null parameter is the object you want to invoke the method on. If the method is static you supply null instead of an object instance
I'm having difficulty understanding the concept of the new keyword. I know its used to instantiate objects; e.g. If I had a class called Superclass, I could create a object of that class by writing:
Superclass supeclassobject = new Superclass();
I understand that but what I dont understand is that this is also acceptable:
E.g. if your were passing a Superclass object to a method which takes it as an argument, then the following would still work:
public void MethodTakingSuperClassObjectAsArugment (new Superclass()){
*CODE HERE*
}
I cant understand how that works. You haven't given a name to the object so how could you refer to it in the method? This makes sense to me:
Superclass sobject = new Superclass();
public void MethodTakingSuperClassObjectAsArugment (sobject){
*CODE HERE*
}
You have a few misconceptions there.
First, there is a method definition, and then there is a method invocation.
Method definition is where you declare your method. You give it modifiers such as public/private/protected, a return type, a name, a list of parameters, an optional throws and a body:
public static int myInt( double myParameter ) {
return (int)myParameter;
}
Here, the parameters must have names. Otherwise, you would not be able to refer to them in the body.
And then there is the method invocation. Within some other method, like main, you call your method:
int a = myInt( 15.7 );
You passed 15.7 without giving it a name. The value that you actually pass in a method invocation is called an argument as opposed to a parameter, which is the formal name and type given in the method definition.
If your method definition included a parameter of the type SuperClass, it would look something like:
public static void myMethod( SuperClass myParameter ) {
...
}
You can't use new in a parameter declaration. But when you invoke the method, and you have to pass an argument to it, you can use:
myMethod( new SuperClass() );
In the same way that you didn't need to give a name to your 15.7 before, you don't need to give a name to your new object now. When Java passes it to the method, the method sees it as the value of myParameter.
Your second misconception is about names of objects. Objects don't actually have names. But they do have references. You can refer to an object from a local variable, from a field or from inside another object. In those cases, you give the reference a name, not the object. So you can do something like this:
Superclass myVar = new SuperClass();
Superclass anotherVar = myVar;
What you have here is two reference variables. You assign a reference to a new object to myVar. And then you assign a reference to the same object to anotherVar. Both myVar and anotherVar refer to the same object. The object does not have a name. You can now do something like myVar = null. But the object will still exist, and you'll be able to access it through anotherVar.
Think of reference variables as arrows. You give the arrow a name, and you can point the arrow at any object of the appropriate type. Or you can assign null to it which means the arrow is not pointing at anything.
Back to the issue of parameters, sometimes you can see something like this:
myMethod( new SuperClass() {
// Code here
} );
This is exactly the same as we did before. It's a method invocation. The code you see in the braces is not the code for myMethod. It is in fact the code for the new object. It's an anonymous class, which extends SuperClass, and has some of its own code in those braces. So the class is defined and an instance is created of it, and that instance - of an anonymous class extending SuperClass is what's being passed as an argument to myMethod. Inside myMethod, it can be accessed with myParameter. It's the same as writing this somewhere in the same file:
private class SomeClass extends SuperClass() {
// Code here
}
And then calling `myMethod` like this:
myMethod( new SomeClass() );
Currently working on a mechanism that allows the deserialization of objects serialized with the Prevayler library. For example:
I have old .jar with classes:
class A {
public B b;
public B getB() {
return b;
}
}
class B {
public int c;
public int getC() {
return c;
}
}
Now I need some kind of migration, because "c" from class "B" need to be cast for example to String.
I'm using custom classloader to load classes and methods:
// 1. make List of URLs to pass to CustomClassLoader class
URL url = new URL(PATH_TO_JAR);
List<URL> urls = new ArrayList<URL>();
urls.add(url);
// 2. Use CustomLoaderClass, to make sure, that loaded classes/methods are not from current project,
// but from the jar specified in URL, since Java class loaders (including URLClassLoader)
// first ask to load classes from their parent class loader.
CustomClassLoader clsLoader = new CustomClassLoader(urls);
java.lang.Class cls = clsLoader.loadClass("A");
// String.class in methods second parametr means, that we should pass String to that method
Method method = cls.getMethod("getB");
// 3. invoke method which returns Object instead "B"
Object obj = method.invoke(null);
I've similary done this with class B.
How I can cast Object obj to "B" so I can invoke method getC from class B?
You wont be able to specify the type on the left hand side of the assignment operator dynamically. At least I know of no way to do that. You will need to check if its a B type first, then explicitly cast it to B. Remember that the obj variable is of type Object, but the object it references is a B, so a getClass() should return B. When you invoke the method, the obj parameter of type Object is the object you want to invoke the method on. It can only be null if the method in question is static. Otherwise, you will need to specify what instance of class A you wish to invoke the method on.
See the invoke doc here: http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)
I really am a little confused here. Normal signature to call accessible class method or variable is (Class/Object).(method/variable). Then how do we give System.out.println()? Since System.out only gives the return type but does not belong to same class. Also in servlets, "this.getServletConfig().getInitParameter("defaultUser")" is not making sense to me, since getServletConfig() and getInitParameter are both member functions of same class, so signature becomes something like, class.method1().method2(), where method1 and method2 are member functions of same class. Can someone please explain..
Example:
Class CascMethodClassB()
{
public CascMethodClassA methodTest()
{
CascMethodClassA obj1 = new CascMethodClassA();
return obj1;
}
} /*Class CascMethodClassB ends*/
Class CascMethodClassA()
{
public int varTest;
public CascMethodClassA()
{
varTest = 7;
}
} /*Class CascMethodClassA ends*/
Class CascMethodClassC()
{
CascMethodClassB obj2 = new CascMethodClassB();
int varTestC = obj2.methodTest().varTest
public static void main(String[] args)
{
System.out.println("varTest in CascMethodClassA is: "+ varTestC);
} /*Class CascMethodClassC ends*/
}
Thankyou,
Fraggy.
Both are different cases.
In the first case, outis a public static member in the System class. The member out is of type PrintStream, so the call
System.out.println()
will call the method println() from the PrintStream object (out).
The second case, is something called method chaining. What happens is that class.method1() will return an object instance, according to Java docs it will return a ServetConfig object. So, you can again call a method from that returned object. Another way of seeing that call is (brackets are redundant, just there so you can visualize the order of the calls):
(ClassName.someMethod1()).someMethod2();
System.out is a public class variable of type PrintStream, not a
method. Therefore you can invoke the println method on it, which returns void.
this.getServletConfig().getInitParameter("defaultUser") makes
perfect sense once you understand chaining method invocations. In
this case, you are:
calling the present instance of Servlet
getting its instance field's value of type ServletConfig
getting whichever String value is returned by invoking the getInitParameter method on the ServletConfig object
Finally, a method's signature is made of the method's name and parameter types
Each non-void method returns a type, which may be a different type to the declaring class, so the chained method/field will have the methods of the returned type (not the class it's called from or the class that the first method is defined in).
For example, to break down System.out.printkln():
System.out // out is a public field of type PrintStream
.println() // println() is a method of PrintStream, not System
My code looks like the following:
class MyObject {
MyField f = new MyField();
}
class MyField {
public void greatMethod();
}
Is there a way to invoke the greatMethod() using reflection on a object of the class MyObject?
I tried the following:
Field f = myObject.getClass().getDeclaredField("f");
Method myMethod = f.getDeclaringClass().getDeclaredMethod("greatMethod", new Class[]{});
myMethod.invoke(f);
But instead it is trying to call greatMethod() on my myObject directly and not on the field f in it. Is there a way to achieve this without need to modify the MyObject class (so that it would implement a method which calls the appropriate method on f).
You were close yourself, you just need to get the declared method and invoke it on the instance of the field that is containted within your object instance, instead of the field, like below
// obtain an object instance
MyObject myObjectInstance = new MyObject();
// get the field definition
Field fieldDefinition = myObjectInstance.getClass().getDeclaredField("f");
// make it accessible
fieldDefinition.setAccessible(true);
// obtain the field value from the object instance
Object fieldValue = fieldDefinition.get(myObjectInstance);
// get declared method
Method myMethod =fieldValue.getClass().getDeclaredMethod("greatMethod", new Class[]{});
// invoke method on the instance of the field from yor object instance
myMethod.invoke(fieldValue);