How to access a static method via a class reference - java

class A {
public static void foo() {}
}
class B {
public static void foo() {}
}
I have Class clazz = A.class; or B.class;
How do I access this via "clazz" assuming it might be assigned either 'A' or 'B'

It is only possible to access those methods using reflection. You cannot reference a class directly, only an instance of type Class.
To use reflection to invoke methodname(int a, String b):
Method m = clazz.getMethod("methodname", Integer.class, String.class);
m.invoke(null, 1, "Hello World!");
See Class.getMethod() and Method.invoke()
You may want to think about your design again, to avoid the need to dynamically call static methods.

You can invoke a static method via reflection like this :
Method method = clazz.getMethod("methodname", argstype);
Object o = method.invoke(null, args);
Where argstype is an array of arguments type and args is an array of parameters for the call. More informations on the following links :
getMethod()
invoke()
In your case, something like this should work :
Method method = clazz.getMethod("foo", null);
method.invoke(null, null); // foo returns nothing

You cannot access static methods without an explicit reference to the class.
No inheritance here, sorry, so you must either do:
A.foo()
or
B.foo()
If you really need it, you will have to do a check:
Object o = .... // eith an A or B instance.
if( o instanceof A ) {
A.foo()
} else {
B.foo()
}
But why don't you just make those functions instance functions, and let them implement an interface?
Okey, you have a class object. Then do:
Class c = ...;
c.getMethod("foo").invoke(null); // null to invoke static methods

According to my lack of knowledge the need for the requested construct is given by the fact that an interface doesn't offer the possibility of static abstract methods. Here is an example:
public enum Cheese implements Yumy {
GOUDA(49),
ESROM(40),
HWARTI(38);
private int percentage;
private Cheese(int fat100) {...} constructor
public void yamyam() {...} // as in Yumy
public static Cheese getByFat(int fat100) {...} // no chance to be part
of interface
};

I hope this isn't making too many assumptions or deviating too far from your question, but if your two classes share a common supertype and creating an instance is tolerable then you can:
Implement a common interface
Create an instance of the object via myClass.newInstance() (class must have an empty constructor)
Call the static method from the instance object.
interface Foo {
void foo();
}
class A implements Foo {...}
class B implements Foo {...}
<T extends Foo> public void something(Class<T> clazz) {
T myInstance = clazz.newInstance();
myInstance.foo();
}
...
something(A.class);
It's a little bizarre but in my case it proved to be useful, and I began by asking the very same question that you did.

Related

Convert a Java Method object to a Function object [duplicate]

class A {
public static void foo() {}
}
class B {
public static void foo() {}
}
I have Class clazz = A.class; or B.class;
How do I access this via "clazz" assuming it might be assigned either 'A' or 'B'
It is only possible to access those methods using reflection. You cannot reference a class directly, only an instance of type Class.
To use reflection to invoke methodname(int a, String b):
Method m = clazz.getMethod("methodname", Integer.class, String.class);
m.invoke(null, 1, "Hello World!");
See Class.getMethod() and Method.invoke()
You may want to think about your design again, to avoid the need to dynamically call static methods.
You can invoke a static method via reflection like this :
Method method = clazz.getMethod("methodname", argstype);
Object o = method.invoke(null, args);
Where argstype is an array of arguments type and args is an array of parameters for the call. More informations on the following links :
getMethod()
invoke()
In your case, something like this should work :
Method method = clazz.getMethod("foo", null);
method.invoke(null, null); // foo returns nothing
You cannot access static methods without an explicit reference to the class.
No inheritance here, sorry, so you must either do:
A.foo()
or
B.foo()
If you really need it, you will have to do a check:
Object o = .... // eith an A or B instance.
if( o instanceof A ) {
A.foo()
} else {
B.foo()
}
But why don't you just make those functions instance functions, and let them implement an interface?
Okey, you have a class object. Then do:
Class c = ...;
c.getMethod("foo").invoke(null); // null to invoke static methods
According to my lack of knowledge the need for the requested construct is given by the fact that an interface doesn't offer the possibility of static abstract methods. Here is an example:
public enum Cheese implements Yumy {
GOUDA(49),
ESROM(40),
HWARTI(38);
private int percentage;
private Cheese(int fat100) {...} constructor
public void yamyam() {...} // as in Yumy
public static Cheese getByFat(int fat100) {...} // no chance to be part
of interface
};
I hope this isn't making too many assumptions or deviating too far from your question, but if your two classes share a common supertype and creating an instance is tolerable then you can:
Implement a common interface
Create an instance of the object via myClass.newInstance() (class must have an empty constructor)
Call the static method from the instance object.
interface Foo {
void foo();
}
class A implements Foo {...}
class B implements Foo {...}
<T extends Foo> public void something(Class<T> clazz) {
T myInstance = clazz.newInstance();
myInstance.foo();
}
...
something(A.class);
It's a little bizarre but in my case it proved to be useful, and I began by asking the very same question that you did.

Invoke a method of an object of type Class

I ll try to set it as simple as possible because it confuses me too.
I got a method returning an object of type Class i.e.
public Class foo(){...}
When I call this method I'm keeping the result in a variable of type Class i.e.
Class obj = new foo();
foo() can return many different classes BUT all of them contain the same method bar().
How can I invoke that method from my obj variable?
I tried obj.bar() but the IDE doesn't seem to like it. I get
Error:(59, 34) error: cannot find symbol method bar()
It seems like you want to group behaviors, that's what Java interfaces do:
interface Barer {
String bar();
}
class Foo implements Barer {
String bar() {
return "I'm a Foo";
}
}
class Fooz implements Barer {
String bar() {
return "I'm a Fooz";
}
}
Then in you code you can have something like:
Barer obj;
if (something) {
obj = new Foo();
} else {
obj = new Fooz();
}
obj.bar()
It makes little sense in fact to store the return value of a constructor in a Class object.
If you really are in the case that you need a Class object (remember that it will just point to the Class, not to the instance you have created), you can use Java reflection:
Class obj = new foo();
Method method = obj.getDeclaredMethod("bar");
method.invoke(null);
if method foo() returns Class, it means it don't return actual instance of the objet on which you want to call bar() method, but the class itself, so it's not possible to call method bar() on Class as Class.class don't have a method bar.
In your code example there is some mistake
Class obj = new foo();
The keyword new mean you're creating a new instance of a class, not you're calling a method on an object.
In fact the right approach would be to use interfaces.
Instead of returning Class from foo method, declare an interface,
public interface MyInterface {
public void bar();
}
and make foo() returning MyInterface instead of Class.
Then you can do
MyInterface obj = tmp.foo();
obj.bar()
If all returned values are objects of classes that implements the same method, you should declare that method in separate interface and let them implement it. Later on you can use generic wildcard like <? extends BarInterface> or change return type to BarInterface.
public interface BarInterface{
public void bar();
}
and
public <T extends BarInterface> foo(){...}
or
public BarInterface foo() {...}

How to get the type of object reference of instance?

Given an interface, an abstract class and a concrete class
interface Interface {
}
abstract class AbstractClass {
}
class C extends AbstractClass implements Interface {
}
I instantiate two instances of my concrete class C like so
Interface a = new C();
AbstractClass b = new C();
System.out.println(getObjectReferenceName(a));// return some.package.Interface
System.out.println(getObjectReferenceName(b));// return some.package.AbstractClass
/*
it return the class name of Object refernce
*/
String getObjectReferenceName(Object o){
// todo
return "class name";
}
How can I get the class name of the reference type?
That is -
a's object reference is some.package.Interface.
b's object reference is some.package.AbstractClass.
To get the name try
System.out.println(a.getClass().getInterfaces()[0]);
System.out.println(b.getClass().getSuperclass());
Output:
interface testPackage.InterfaceClass
class testPackage.AbstractClass
If you want to check if an object is an instance of a class, try instanceof.
Edit:
If you want to get the type the variables were declared with, you can use reflection. This works if these are fields, in other words, if they are declared as class fields, no local variables.
System.out.println(Test.class.getDeclaredField("a").getType()); // Test is the name of the main' method class
System.out.println(Test.class.getDeclaredField("b").getType());
a.getClass().getInterfaces() gives you Array that contain object of Class class that represent all interfaces implemented by class of object a.
i.e. a.getClass().getInterfaces()[0].getName() gives you InterfaceClass
b.getClass().getSuperclass().getName() gives you AbstractClass
This might seem like a stupid answer but
// right here
// |
// v
Interface a = new C();
Also you've added a hypothetical method that returns the name of the reference type but
static String getReferenceType(Object o) {
// the reality is o is always Object
return Object.class.getName();
}
There's not really a situation where you need to do some program logic based on the type of a reference because you always know the type of the reference. It's in your own declaration. The situation where you need to call a method or instanceof operator is when you have it the other way: when you don't know the actual type of the object.
You can go the java.lang.Class to access methods and then invoke them to get different information. If you want to know which class is based to instantiate an object, you could use referenceVariableName.getClass(); to get its super class, referenceVariableName.getClass().getSuperclass() to do that; to know interfaces, then you can use referenceVariableName.getClass().getInterfaces()[0] (the first interface since there are many interfaces maybe).
Try this:
public class ObjectReferenceName {
Interface a = new C();
AbstractClass b = new C();
C c =new C();
static String getObjectReferenceName(String fieldName) throws NoSuchFieldException{
return ObjectReferenceName.class.getDeclaredField(fieldName).getType().getName();
}
public static void main(String[] args) throws NoSuchFieldException {
System.out.println(ObjectReferenceName.getObjectReferenceName("a"));
System.out.println(ObjectReferenceName.getObjectReferenceName("b"));
System.out.println(ObjectReferenceName.getObjectReferenceName("c"));
}
}

How to use AOP to intercept a method call in super on an argument?

I'm extending a class and overriding a method. All I want to do is to call super, but with a modified argument that gets intercepted upon one of its methods is called. An example makes it more clear:
// Foo is an interface and also this method is part of an interface
#Override
public void foo(Foo foo) {
// I want to intercept the call to foo.bar() in super
super.foo(foo);
}
I'd rather use a tool that doesn't require a compiler of its own. What would be the optimal one?
Given that Foo is an interface, you might consider using a dynamic proxy that would:
Wrap the original foo
Intercept all message and forward them to the original foo
There is a complete example in the above link. Here is just the idea:
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
System.out.println("before method " + m.getName());
return m.invoke(obj, args);
}
}
Foo original = ... ;
Foo wrapper = (Foo) java.lang.reflect.Proxy.newProxyInstance(
original.getClass().getClassLoader(),
original.getClass().getInterfaces(),
new DebugProxy(original));
wrapper.bar(...);
Note that if Foo was not an interface, you could still subclass Foo and override all methods manually so as to forward them.
class SubFoo extends Foo
{
Foo target;
SubFoo( Foo target ) { this.target = target };
public void method1() { target.method1(); }
...
}
It's pseudo-code, and I haven't tested it. In both cases, the wrapper allows you to intercept a call in super.
Of course, the wrapper has not the same class as the original Foo, so if super uses
reflection
instanceof
or access instance variables directly (not going through getter/setter)
, then it might be problematic.
Hope that I understood your problem right and that it helps.

Calling static method on a class?

Say, I have a reference to a Class object with SomeType having a static method. Is there a way to call that method w/o instantiating SomeType first? Preferably not escaping strong typing.
EDIT: OK, I've screwed up.
interface Int{
void someMethod();
}
class ImplOne implements Int{
public void someMethod() {
// do something
}
}
Class<? extends Int> getInt(){
return ImplOne.class;
}
In this case someMethod() can't be static anyways.
I'm not sure exactly what the situation is, but if you're looking to execute the static method on a class without knowing the class type (i.e. you don't know it's SomeType, you just have the Class object), if you know the name and parameters of the method you could use reflection and do this:
Class c = getThisClassObjectFromSomewhere();
//myStaticMethod takes a Double and String as an argument
Method m = c.getMethod("myStaticMethod", Double.class, String.class);
Object result = m.invoke(null, 1.5, "foo");
A static method, by definition, is called on a class and not on an instance of that class.
So if you use:
SomeClass.someStaticMethod()
you are instantiating nothing (leave aside the class loading and instantiation of the SomeClass class itself, which the JVM handles and is way out of your scope).
This is opposed to a regular method called on an object, which has already been instantiated:
SomeObject o = someObject; // had to be instantiated *somewhere*
o.someMethod();
Since you talk about a Class object, I assume that you're interested in Java reflection. Here's a brief snippet that does what you're trying to do:
Class someClass = SomeType.class;
Method staticMethod = someClass.getMethod( "methodName", ... );
// pass the first arg as null to invoke a static method
staticMethod.invoke( null, ... );
Yes. That's what static methods are all about. Just call it. SomeType.yourStaticMethodHere().

Categories

Resources