I'm loading a class with following statement:
Class classToLoad = Class.forName("com.somePackage.SomeotherPackage.classname" );
Later i wd use reflection to get the methods of this class. now for invoking the methods with methodname.invoke() function i'd require the object of the loaded class. thus i want to create the object of the loaded class. I try to do it this way:
Object obj = classToLoad.newInstance();
but the problem in this is that this way i don't get the object of the class loaded but i get object of Object class.
Now if i want to call the functions of the loaded class, i do it like:
methodName.invoke(obj);
it throws an exception:
java.lang.IllegalArgumentException: object is not an instance of declaring class
can anybody please help?
Update on the problem:
The problem is that i need the left hand side of the assignment to be of a different class type and that class type will be decided on run time
For the below statement:
Object instance = clazz.newInstance();
"instance" should be of the "clazz" type and not the "Object" class.
How can i achieve this?
It works fine when everything's set up correctly:
import java.lang.reflect.Method;
class Foo {
public Foo() {
}
public void sayHello() {
System.out.println("Hello");
}
}
public class Test {
public static void main (String[] args) throws Exception {
Class<?> clazz = Class.forName("Foo");
Method method = clazz.getMethod("sayHello");
Object instance = clazz.newInstance();
method.invoke(instance); // Prints Hello
}
}
My guess is that the method you've fetched (methodName) wasn't actually fetched from classToLoad.
You can also just cast the return type and invoke the method directly.
public class Foo{
void HelloReflection(){
System.out.println("Hello reflection");
}
public static void main(String[] args){
try{
Foo o = (Foo) Class.forName("Foo").newInstance();
o.HelloReflection();
}catch(Exception e){
e.printStackTrace();
}
}
}
java.lang.IllegalArgumentException: object is not an instance of declaring class
This can be thrown if the method has no arguments and not found in your object's class. Probably You are calling the invoke method on the wrong object or your fetched method is wrong for your object.
The problem is that i need the left hand side of the assignment to be of a different class type and that class type will be decided on run time. ... How can i achieve this?
Use some language other than Java. Java is statically typed, which basically means you're not allowed to do exactly what you just asked how to do. The other answers here correctly show how to invoke a method without knowing the type of an object at compile time, but you'll never be able to set the type of a variable at runtime.
Related
Please tell me if I have the proper understanding of the following code:
public class Test {
public static void main(String[] args) {
A a = new A();
a.print();
}
}
class A {
String s;
A(String s) {
this.s = s;
}
void print() {
System.out.println(s);
}
}
The line “A a = new A();” invokes the class/constructor to create a new object with reference variable “a”. Class A has a defined constructor that requires a string argument, thus it does not have the default constructor. This means that the instantiation without any string arguments causes a compiler error.
If I were to add a string argument into the instantiation, e.g. A a = new A("goldfish"); the program would compile and run.
I am not sure if I have used the right vocabulary for this, so feel free to correct anything that is inaccurate/confusing. Thanks!
Your understanding is pretty much correct. The one thing that I would change is "create a new object" to "create a new instance of A" with a reference to a java.lang.String in parameter s. In this case the constructor assigns that parameter to a field, but it can do something else with it entirely (such as use it to calculate a different value for some field).
What you wrote is roughly correct.
To be more precise: "invokes the class/constructor" is not entirely correct. A a = new A(); intends to invoke the constructor (invoking a class doesn't mean anything).
Though constructors are not methods, you can think of them a bit like methods: if your class has defined a method like so :
public void myMethod(String s) { ... }
Then trying to call myMethod() without any argument would fail. It's the same here.
I am naive to java programming.
How to access an object created in one class into another class.
Class A
{
Obj
}
Class B
{
//Here i want to use Obj
A.Obj
}
For the above i declare Obj as public static, but when i use it in Class B as A.Obj, it is returning a syntax error saying
"Cannot make a static reference to the non-static field A.Obj".
Am i missing something here? Are there any other ways?
Yes you cant access without having an instance of A. You could do something like:
System.out.println(new A().Obj);//or define Obj as static in A class.
Note - You should encapsulate your Obj and access it via getter method.
You should use provide a get method or use that object in static method as well. for your information static will not garbage collected unless the execution gets stopped for more about your answer use this answer's reference
You need first to declare your Obj in class A as static
class A {
static Object object = new Object();
}
Then you can use it
class B {
A.object //in the class cannot be accessed directly
Object x = A.object; //can use it to assign a value
public Object Foo() {
A.object //in a method can be accessed directly
return A.object; //here as expression result
}
}
Suppose the classes has code like this:
class C {
public static void show() {
}
}
class CTest {
public static void main (String[] args) {
C.show();
}
}
Then will it be perfectly legal to conclude that while referring to class C to access the static method show() here, behind the scene Java is actually calling the show() method through Java reflection ?
I.e. is it actually doing something like this
Class test = Class.forName(C);
test.show();
to call static methods?
If not, then how is it actually calling the static methods without creating objects?
If the above explanation is true, then how we'll justify the statement that "static members are only associated with classes, not objects" when we're actually invoking the method through a java.lang.Class object?
The JVM doesn't need to do anything like Class.forName() when calling a static method, because when the class that is calling the method is initialized (or when the method runs the first time, depending on where the static method call is), those other classes are looked up and a reference to the static method code is installed into the pool of data associated with that calling class. But at some point during that initialization, yes, the equivalent of Class.forName() is performed to find the other class.
This is a specious semantic argument. You could just as easily say that this reinforces the standard line that a static method is associated with the class rather than any instance of the class.
The JVM divides the memory it can use into different parts: one part where classes are stored, and one for the objects. (I think there might have been third part, but I am not quite sure about that right now).
Anyways, when an object is created, java looks up the corresponding class (like a blueprint) and creates a copy of it -> voila, we have an object. When a static method is called, the method of the class in the first part of the memory is executed, and not that of an object in the second part. (so there is no need to instantiate an object).
Besides, reflection needs a lot of resources, so using it to call static methods would considerably impact performance.
For extra info:
The called class will get loaded when it's first referenced by calling code.
i.e. The JVM only resolves and loads the class at the specific line of code that it first needs it.
You can verify this by using the JVM arg "-verbose:class" and stepping through with a debugger.
It will call ClassLoader.loadClass(String name) to load the class.
You can put a println statement into the ctor, to verify, whether it is called or not:
class C {
public static void show () {
System.out.println ("static: C.show ();");
}
public C () {
System.out.println ("C.ctor ();");
}
public void view () {
System.out.println ("c.view ();");
}
}
public class CTest
{
public static void main (String args[])
{
System.out.println ("static: ");
C.show ();
System.out.println ("object: ");
C c = new C ();
c.view ();
c.show (); // bad style, should be avoided
}
}
As we know that we do not have to add any return type to a Java constructor.
class Sample{
.....
Sample(){
........
}
}
In Objective C, if we create a constructor, it returns a pointer to its class. But it is not compulsory, I think.
AClass *anObject = [[AClass alloc] init];//init is the constructor with return type a pointer to AClass
Similarly, Is the constructor converted to a method which return a reference to its own class??
Like this:
class Sample{
.....
Sample Sample(){
........
return this;
}
}
Does the compiler add a return type a reference to same class to constructor?
What is happening to a constructor?
Any reference to study this?
EDIT:
Actually i want the answers to be at byte code level or JVM level or even below.
Many have answered how constructors are defined in Java.
At the JVM level, static initialisers and constructors are methods which return void. Static initialisers are static methods, however constructors use this and don't need to return anything. This is because the caller is responsible for creating the object (not the constructor)
If you try to only create an object in byte code without calling a constructor you get a VerifyError. However on the oracle JVM you can use Unsafe.allocateInstance() to create an object without calling a constructor,
The static initialiser is called <cinit> which takes no arguments and the constructor is called <init>. Both have a void return type.
For the most part, this is hidden from the Java developer (unless they are generating byte code) however the only time you see these "methods" in stack traces (though you can't see a return type)
While constructors are similar to methods, they are not methods. They have no return type, are not inherited, and cannot be hidden or overridden by subclasses.
Constructors are invoked by class instance-creation expressions (basically, the use of new), by explicit invocation from other constructors (using this(...) or super(...) syntax), and by the string concatenation operator. There is no other way to invoke a constructor (in particular, they cannot be invoked like other methods).
See Section 8.8 of the Java Language Specification for more info.
Is the constructor converted to a method which return a reference to its own class??
No but yes, if it is specified to do so.
Does compiler add a return type a reference to same class to constructor ??
No it does not
What is happening to a constructor??
It is the method, which runs when the object is created. Typically, by using "new" keyword. It Might perform some preliminary task, or return something or assign some values during construction.
Any reference to study this.??
http://www.javaworld.com/javaworld/jw-10-2000/jw-1013-constructors.html
http://www.javabeginner.com/learn-java/java-constructors
Constructors are similar to methods except that they use the name of the class and have no return type. The whole purpose of using constructors is to create an object (an instance of a class) and allocate it (via new keyword) in the memory (the heap) and also initialize any fields if available.
Constructors are invoked via the special java keyword new, which creates (and initializes) an object of the specified concrete type.
I suppose you could say the combination of new and the chosen constructor "returns" an object, which in java is of course a pointer under the covers
Constructor returns the class reference of the class for which its being called.E.g.-
class A {
int x;
A(int a) {
x = a;
}
}
class B {
public static void main(String asd[]) {
A a = new A(4);
System.out.println(a);
}
}
Here after calling the constructor A(...), this constructor will return the reference of type of class A to caller( i.e. A a = new A(4) ).
The return type of the constructor is corresponding class type.
package com.ie.test;
import java.lang.reflect.*;
public class a {
public a() {
super();
System.out.println("*** no-arg constructor ***");
}
public static void main(String[] args) {
Constructor[] constructors = a.class.getConstructors();
for (Constructor constructor:constructors) {
int i = constructor.getModifiers();
AnnotatedType annotatedType = constructor.getAnnotatedReturnType();
System.out.println("***********Returntype *******"+annotatedType.getType());
System.out.println("*******constructor *****"+Modifier.toString(i));
}
Method[] methods = a.class.getDeclaredMethods();
for (Method method:methods) {
int i = method.getModifiers();
// Class c = method.getReturnType();
AnnotatedType annotatedType = method.getAnnotatedReturnType();
System.out.println("***********Returntype *******"+annotatedType.getType());
// System.out.println(c);
System.out.println("*******methods*******"+Modifier.toString(i));
}
}
public int m1() {
System.out.println("***************");
return 0;
}
}
I'm working with the basics of Java reflection and observing information on methods of classes. I need to get a method that matches specifications as described by the getMethod() function. However, when I do this I get a NoSuchMethodException, and I was hoping you could tell me why my implementation is incorrect.
static void methodInfo2(String className) throws ClassNotFoundException,
NoSuchMethodException{
Class cls = null;
try{
cls = Class.forName(className);
} catch(ClassNotFoundException e){
e.printStackTrace();
}
System.out.println("Cls: "+cls);
Method method1 = cls.getMethod("test", null);
System.out.println("method1: "+method1);
}
EDIT1:When I print out "Cls: "+cls, the output is "Cls: class a8.myclass2". Why does it append the class part? (the a8 is correct, so don't worry about that) /EDIT1
This is the function I use to read in a class from my main function, and then I want to getMethod() with the parameters "test" and null, where "test" is the name of the method and null means the method has no parameters. The class I am reading in is called myclass2 which is here:
package a8;
public class myclass2 {
void test(){
//"takes no parameters"
//"returns bool"
//"name starts with test"
//return true;
}
}
As you can see, the method does infact exist in the class. If you could point out my mistake, I would really appreciate it.
Make your test method public. I believe Class.getMethod() is limited to public methods.
Without you posting the exact exception and your output, its hard to tell, but I suspect it is because the classes are in two separate packages, and since the default modifiers for a method are just protected it fails.
Use getDeclaredMethod() to get a method that isn't normally visible.