class className {
void method1(void){
*do something
}
}
Is there any way to get the name of the class method above, and/or perhaps a pointer? I wanted to make a GUI object generated by my methodGenerator class to be displayed depending on the className and its class methods mentioned. I am learning Java at the moment.
For example, if className1 has method1, and method2; and className2 has only method1.
In Java, you can use reflection to get method names. There are several ways of doing this, for example, if you want all the methods of the class, you can do something like this:
Method[] methods = ClassName.class.getMethods(); // Gives you all the methods
You can invoke the method by calling invoke() on the instance of Method. If the method is private, you will have to make it accessible by calling setAccessiable(true) on the Method and then calling invoke() on the instance of that Method
Related
Currently, I have a number of nested classes inside an outer class. Each nested class has an overriden toString method. My goal is to iterate through these nested classes to access the value returned by the overriden toString without initializing every single nested class. I've tried iterating through the array returned by Class#getDeclaredClasses
The simplified outer class:
class MyClass {
static class NestedClassOne {
#Override
public String toString() {return "One";}
}
static class NestedClassTwo {
#Override
public String toString() {return "Two";}
}
}
The method I've tried, using the Class#getDeclaredClasses array:
for (Class<?> NestedClass : MyClass.class.getDeclaredClasses()) {
System.out.println(NestedClass.toString());
}
This method, to my dismay, only prints the following:
class ... MyClass$NestedClassTwo
class ... MyClass$NestedClassOne
Your toString() is invoked directly on the class object. I.e., it calls Class<T>.toString() not NestedClassOne.toString(). For that you need to use reflection:
Class<NestedClassOne> clazz = NestedClassOne.class;
Method method = clazz.getMethod( "toString" );
NestedClassOne obj = clazz.newInstance();
Object result = method.invoke( obj );
System.out.println( result );
I'll repeat my comments however:
This sounds like a bad idea. You really shouldn't be using reflection like this. An enum or something similar would likely be a better fit.
It's just kind of obviously super brittle. It throws numerous exceptions, which enums won't. If the code structure changes at all (changing to a different constructor for example) it breaks. If the method name changes, the compiler can't detect it. Etc. I wouldn't want to maintain code that works the way you are asking for.
My goal is to 1) iterate through these nested classes to 2) access the value returned by the overridden toString without initializing every single nested class.
The first part you are doing. The second part is not possible.
The toString() methods you are trying to call are instance methods.
You can't call an instance method until you have created an instance.
You can't create an instance of a class without triggering1 the static initialization of the class.
What your attempted code is actually doing is calling the toString() method on the Class objects. That gives you the names of the classes.
#markspace's answer shows how to create an instance and call the toString() method via reflection. The caveats are that it assumes that each class has a no-args constructor, and that creating the instances doesn't have undesirable side-effects.
1 - There are scenarios involving classes with cyclic dependencies where an instance of a class may be created before its static initialization has completed.
I agree with #markspace's comments. I'm not sure what the real purpose of this is, but there is likely to be a better (more robust) way than calling toString() methods. (For example ... using a custom annotation with runtime retention.)
Even if there isn't, the constraint of not initializing the classes seems artificial to me: is this a premature optimization?
Following this tutorial:
http://developer.android.com/training/notepad/notepad-ex2.html
In Step 2, this method gets called:
registerForContextMenu(getListView());
which is a public method of Activity. Now, I'm a bit of a Java newbie here - I thought if you wanted to call an instance method of a superclass you needed to preface it with this. E.g.
this.registerForContextMenu(getListView());
Is it just a style thing here? Is there any difference between
this.registerForContextMenu
and simply
registerForContextMenu
No, there is no difference.
You don't have to use this., but it is often done anyway to make the code clearer.
For one thing, it makes it easy to tell if a method is static or not if you use the convention of calling instance methods like this:
this.registerForContextMenu()
and static methods like this:
ClassName.staticRegisterForContextMenu()
you do not have to use this. If you ommit it it is assumed you called method in this scope. One particular example when this may help could be i.e.:
Boolean someVar;
public function setMe( Boolean someVar ) {
this.someVar = someVar;
}
In this case, w/o this you would get the error.
To call a method of superclass either you need object of superclss or keyword super .
eg.
superObject.superclassMethod();
super.superclassMethod();
this is a reference of the current object. this can be used to call method of a class in which it is used. this can never be used to call a superclass method.
As for
this.registerForContextMenu()
and
registerForContextMenu()
no such difference. you can use either of them.
Both ways are correct for calling a method on the current (this) instance of the class. Non private methods are inherited from super classes, so you can use the same syntax to call such methods.
If I had a method signature
public void myMethod(SuperClass s){
}
and SuperClass has three subclasses, is there any way within myMethod I can get the class name of the subclass which was passed in?
Not sure if it's important, but SuperClass is abstract.
is there any way within myMethod I can get the class name of the subclass which was passed in?
Yes, by using the getClass method:
public void myMethod(SuperClass s){
System.out.println(s.getClass());
}
Remark 1:
This does however sound to me like a Bad Design™.
Whatever you want to do in myMethod consider having a method for it in SuperClass (provide a meaningful default implementation, or make it abstract to force subclasses to implement the method) and call this method on s in your method:
public void myMethod(SuperClass s){
s.abstractMethod();
}
Remark 2:
If myMethods logic is seemingly unrelated to the purpose of the SuperClass and you don't want to put the myMethod code inside this class, consider implementing the visitor pattern instead.
If I do this in Java to call a method name from a class dynamically, it works.
MainApp app = new MainApp();
Method meth = app.getClass().getMethod("myMethod", MyParameterType.class);
//call method
meth.invoke(app, new MyParameterType("hello"));
But this worked because I know the constructor in the invoke method. But if I were to pass the Method object as a parameter to some other classes, and I don't know who is the constructor, I cannot invoke the method any more. Even if I know, I may not want to create a different object to just make a call to the method. For eg:
//This is in the class call MainApp.java.
//There is a method in MainApp.java that looks this way: myMethod(MyParameterType param);
MainApp app = new MainApp();
OtherClass myClass = new OtherClass();
Method meth = app.getClass().getMethod("myMethod", MyParameterType.class);
myClass.callMe(meth);
//Inside OtherClass.java
public void callMe(Method meth) {
//call method
meth.invoke(########, new MyParameterType("hello"));
}
In this case, what should I put for the ######## parameter? Within the context of OtherClass.java, the base constructor object wouldn't be known. And why would I need if since meth is already a Method type that I just call like a function?
Thanks
Assuming it's an instance method, you've got to have an instance to call the method on, just like anything else. How you get hold of that instance will depend on what you're trying to do; you could pass in a Constructor, or a reference to an existing object, or some interface which will create the instance when you ask it to... we can't really give you any advice on which approach is the most suitable without knowing what you're trying to do.
If it's a static method, you can pass null for the first argument.
What it seems you are looking for or thinking about is the concept of `lambda functions``. Those can be called in isolation.
A Method type is not a standalone method, but more like a 'path' into an object. Compare this with a relative URL like /subscribe.html. Out of context this is pretty useless, but when bundled with a site like www.example.com it makes sense.
As such, Method can only be used in combination with an instance. (edit: as John mentioned, unless it's a static method of course which do not need instances)
If you can safely invoke a method without providing an instance, it should be a static method, in which case any instance provided is ignored, you can give it null.
If you have to provide an instance of the object, there is no way around this.
If the developer who write the method has labelled it non-static incorrectly, I suggest you discuss with them why they did it.
Is there any way in Java to store a reference to a class? Here's what I want to do:
public class Foo
{
public static void doSomething() {...}
};
SomeClass obj = Foo;
obj.doSomething();
Is there some class "SomeClass" which lets me store a reference to a class, such that I can later use that stored object to call a static member of the original class?
The obvious thing would be class Class:
Class obj = Foo.class;
obj.someMember().doSomething();
but I haven't figured out which of class Class's members might act as "someMember()"... none of them, I think.
Does anyone know if what I'm trying to do is possible in Java?
You can dynamically get a method from a Class object using the getMethod() methods on the class. If a method is static, then the "object" parameter of "invoke" will be null.
For example, the "obj.someMember()" above would be something like this:
obj.getMethod("someMember", null).invoke(null, null);
The extra nulls are because your method requires no parameters. If your method takes parameters, then they will need to be passed in accordingly.
This will throw various checked exceptions, so you'll need to handle those as well.
Once you've invoked the method, it will return an Object. You'll want to cast that to whatever type you're expecting, and then you'll be able to run the "doSomething()" method directly on that.
This is using a trick called reflection, if you'd like to read up more on it. :)
If you are using jdk1.5 or above, annotation will be a choice when you want to get metadata of Class.