Calling static method on a class? - java

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().

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.

Interface, abstract class and inheriting subclass with same Method, that gets different type arguments, which is used?

I have these interface and classes:
public interface AlternateLight {
public String change(long time);
}
public abstract class AbstractLight {
public String change(int time) {
return "AbstractLight Method was used";
}
}
public class DistinctAlternateLight extends AbstractLight implements AlternateLight {
public String change(long time) {
return "DistinctAlternateLight Method was used";
}
}
Now I call the method change() with following main-method:
public class WhatUsedTest {
public static void main(String[] args) {
AlternateLight al = new DistinctAlternateLight();
System.out.println(al.change(100));
}
}
It prints "DistinctAlternateLight Method was used", but why? I thought since I didn't put a "L" behind the 100 as argument, it would call the method of the abstract class, because its method takes integers. With missing out on the "L", I guessed the compiler wouldn't handle the 100 as a long value and call the method taking longs, but it does. Why is that so?
It's due to the polymorphism, if you declare your variable with AlternateLight class and this type has only acces to change(long time).
be careful. If you use interface as reference type and assign an object of implementing class to it then you can call only those methods that are declared inside the interface. This is quite obvious because the implementing class can define methods of its own that are not a part of the contract between the interface and class. So, to call those methods you have to use the class as reference type as following:
DistinctAlternateLight al =new DistinctAlternateLight();
The method with the closest match to your type arguments will be used.
But for compatible numerical, the deepest declared one.
You can also see that the type of "al" object is an interface type, so you can`t call the method from super class without casting, you also can`t call any method from AbstractLight without casting. You can only call methods there were declared in interface class. In that case, compiler will favour the method from the interface class.
You can force the compiler to call a method from abstract class if you write something like that:
System.out.println(((AbstractLight)al).change(100));

easy to refactor a static method call from an abstract class

I have lots of refences to this
MyAbstractClass.myStatic()
And I want to change them to non static method of an normal class, that is
myOtherClass.myMethod()
is there an easy way to do this using intellij ?
If MyOtherClass has a no-parameter constructor and you're OK calling it on a new instance every time, you could change the original method to
public void myStatic() {
new MyAbstractClass().myStatic();
}
and then inline the method. Similarly, if MyAbstractClass could hold a public static instance of MyOtherClass then the original method could be inlined.

Calling subclass's static method from parent class

This is a strange question but I was wondering if there was a way to "override" a parent class's static method in a subclass and call that subclass's static method from the parent class.
It would look something like this
public class parentFoo {
public static void <T extends parentFoo> printFoo () {
T.printFoo();
}
}
public class childFoo extends parentFoo {
public static void printFoo() {
System.out.println("Foo");
}
}
so you could do something like this in your code
//print out "Foo"
parentFoo.<childFoo>printFoo();
This isn't working for me but I was wondering if there is some way to make this possible. Right now I get a stack overflow because it only calls the parent class's printFoo method.
You cannot override static methods. You can however define static methods of the same name. If you do that then you can specify which one is called from the class type
ChildFoo.printFoo(); // call child foo
ParentFoo.printFoo(); // call parent foo
ParentFoo foo1 = new ChildFoo();
foo1.printFoo(); // ParentFoo still called because of type of reference foo1 not its value
ChildFoo foo2 = new ChildFoo();
foo2.printFoo(); // ChildFoo called because of type of reference foo2 not its value
There's no way to to call a static method based on a generic type parameter.
The answer to the question below provides a reasonable workaround.
Calling a static method using generic type
Replace
parentFoo.<childFoo>printFoo();
with
childFoo.printFoo();
Why would you need to override static methods? (which isn't possible) What are you trying to accomplish?
A polymorphic call only makes sense for objects. Since statics aren't part of an object, but of a class, it doesn't.

How to access a static method via a class reference

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.

Categories

Resources