I'm following a java tutorial, i find this piece of code:
//load the AppTest at runtime
Class cls = Class.forName("com.mkyong.reflection.AppTest");
Object obj = cls.newInstance();
//call the printIt method
Method method = cls.getDeclaredMethod("printIt", noparams);
method.invoke(obj, null);
My question is: if i don't know the class type, is not much easier (and faster) try to cast the object instead of invoking methods in that way?
Why (and when) i should use this way?
Read this question
What is reflection and why is it useful?
It says:
"For example, say you have an object of an unknown type in Java, and you would like
to call a 'doSomething' method on it if one exists. Java's static typing system
isn't really designed to support this unless the object conforms to a known
interface, but using reflection, your code can look at the object and find out if
it has a method called 'doSomething' and then call it if you want to."
You can find a good tutotial here http://tutorials.jenkov.com/java-reflection/index.html
One reason of doing it this way, not sure if in your case:
Method method = cls.getDeclaredMethod("printIt", noparams);
method.invoke(obj, null);
will allow u to call printIt even if it is private.
But if you cast to your class object then u will not be able to call private methods.
If i don't know the class type, is not much easier (and faster) try to cast the object instead of invoking methods in that way?
Why (and when) i should use this way?
I assume you mean "If I know" not "If I don't know" above.
If you have com.mkyong.reflection.AppTest at compile-time, then you wouldn't need to use reflection to use it at all. Just use it:
// In your imports section (although you don't *have* to do this,
// it's normal practice to avoid typing com.mkyong.reflection.AppTest
// everywhere you use it)
import com.mkyong.reflection.AppTest;
// ...and then later in a method...
//load the AppTest at runtime
AppTest obj = new AppTest();
//call the printIt method
obj.printIt();
If you don't know the class at compile-time, you can't cast the result of newInstance to it, because...you don't have it at compile time.
A common middle ground is interfaces. If com.mkyong.reflection.AppTest implements an interface (say, TheInterface), then you could do this:
//load the AppTest at runtime
Class cls = Class.forName("com.mkyong.reflection.AppTest");
TheInterface obj = (TheInterface)cls.newInstance();
//call the printIt method
obj.printIt();
At compile-time, all you need is the interface, not the implementing class. You can load the implementing class at runtime. This is a fairly common pattern for plugins (like, say, JDBC implementations).
Related
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 6 years ago.
SuperClass object = new SubClass();
Why use a superclass to instantiate a subclass object like above? Because the only way i learnt to instantiate an object is to:
SubClass object = new SubClass();
I'm learning java.
You may have a method that only takes an instance of SuperClass. Since SubClass is a SuperClass, you can use an instance of SubClass and treat it as SuperClass.
The same behavior is used when working with interfaces:
List someList = new ArrayList();
That's the beauty of polymorphism. It allows you to change out the implementation of the class' internals without breaking the rest of your code.
This is known as polymorphism.
Imagine the following example:
Musician musician = new Pianist();
or
Musician musician = new Drummer();
Suppose Musician class has a method: play(). It doesn't matter who the musician is, if you call play method, you'll know how to play the determined instrument, base on concrete class, on this case, no matter if Pianist or Drummer.
Each concrete class, overwriting its play() method, can play on your own:
e.g. for Pianist class: play() { playsBeethoven(); }
For detailed information, please check http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
It's always good to remember to use it with inheritance http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
The main reason to do the former is for function calls that expect the super class. If you have a class A that has a method like this
public static void insert(SuperClass b) {
//do something
}
and you have the
SuperClass object = new SubClass();
you can do
A.insert(object);
But if you do
SubClass object new SubClass();
you can't do
A.insert(object);
unless you add a method like this to A
public static void insert(SubClass b) {
//do something
}
This helps you cut down on redundant or copied code and keep things cleaner.
All you're doing is telling the JVM what the type of the reference is at compile time.
In the first case, you're saying that the object reference has static type of the super class. When you create a new sub-class object, you can have that reference point to it because a sub-class IS-A super class instance.
That is one of the main reasons you use inheritance. You treat the SuperClass as an abstraction, and at compile time you don't need to know the derived type, or another class doesn't need to know the derived type. This allows you to use references to SuperClass while using polymorphism to call the methods of the derived class.
This enables you to
a.) Create factories so that you don't need to know the type at compile time, and you have some runtime method that creates the derived types. Think COM, GStreamer, DirectShow, Glib, etc...
b.) Hide complexity to other objects by only exposing the base type references even though they are instances of the derived type. Think about the methods that return object or take an object reference as an argument.
c.) many more possibilities, but those are probably the most relevant two uses to you.
What I wanna do is a method that can
generate instance of Class X (a class variable passed in arg) and
override some of it's method
More specifically, the parent class X I want to override contains
Contains no default constructor (e.g. all constructors with args)
Constructors calling non-private method within the same class
Originally I thought it's quite simple to use reflection or something similar,
Then I found there's limitation on implementing my requirement.
For refection: Can only override "interface" via java.lang.reflect.Proxy
http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
for cglib: it cannot create instance of no default constructor and constructor calling non-private member methods
http://insufficientinformation.blogspot.com/2007/12/spring-dynamic-proxies-vs-cglib-proxies.html
I think this is achievable, since Mockito can do all kinds of method injection runtime.
Please anyone give some advise, Thanks.
The pseudo-code I image is like this:
createAndOverride(Class X) {
X newObj = X.newInstance(args) {
#override
methodOfX(args2) {
...
}
}
return newObj;
}
Original problem scenario
I was intended to test a Class which has several methods calling X1.get(), X2.get(), X3.get()
In some test case, I need to make Xn.get() to return something I can control for test (e.g. null)
Due to below constraint:
But due to mock tool restriction to JMock 1.0 (I have no control :( ), so I cannot just simply mock Xn.get() to returns "someSpecifiedObjects"
Xn has no null constructors and constructors calling non-private member
My workaround is self made Xn Class and pass them to test case to let Cn.get() to be expected
code example:
ClassToTest.SomeMethod(new X1() {
#override
get() {
return someSpecifiedObjects;
}
});
And this kind of thing is spread-ed over the Test Case.
Therefore, In order to reduce duplicate code, I would like to build a method to generate Xn instance with specified overrided method for test. e.g.
X1 x1 = createAndOverride(X1);
Then, the problem of this post comes
are you looking for something like javassist? You can instrument code and inject your methods at runtime. I personally try to avoid byte code manipulation as much as possible. Can you not have these overrides in your code base rather than doing on the fly? May be something like wrappers?
So what I think you need is a similar functionality to C#'s Reflection.Emit:
Using Reflection.Emit to create a class implementing an interface
Java Equivalent of Reflection.Emit
Dynamically Create Java Classes With JavaClassCreator
While I haven't done this myself, I think you should be able to use reflection/emission and dynamic type creation in order to achieve what you're looking for. However, I would still like to mention that if you're trying to test "functionality" that's not int he code path of the function you're testing, then you probably shouldn't be testing it at all. For example:
SomeObjectInterface get()
{
if(_someObjectStateIsSet)
{
// Return a concrete implementation A
return new ConcreteImplA();
}
else
{
// Return a concrete implementation B
return new ConcreteImplB();
}
}
In this case get has no code path that would return null, so you shouldn't need to test for null. I'm not sure if I understood your question 100% correctly, especially why you're testing for null, but consider the above advice and see what works for you.
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.
I need to write a function that accepts an object , but I want to enforce in the function call (not after the function is called) that the object is an interface.
Meaning , I want to make sure this is an Interface at compile time , not on run time.
What do I mean?
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
In this example , the passed object is an interface , and I want that the MyClass.register function to enforce the this requirment in it's declaration.
I don't know which interface I'm going to get , and there is no use defining another interface to be implemented by all other implementation , because I need the real interface.
To accept only objects that implement an interface as argument, use the interface as type, i.e.:
void acceptMaps(Map argument) {
}
can be called with objects implementing the Map interface, like HashMap but not with Strings for instance as they do not implement Map.
Is this what you meant with your question?
Edit in this example, objects implementing SortedMap which extends Map are accepted too, so in your case you could create a BaseInterface and extend that in the interfaces (like AcceptedInterface extends BaseInterface) you want to be accepted by your .register(BaseInterface arg) method.
You can't instantiate an interface so you would never be able to create one to send in. You can specify an interface in the parameters for the function and only objects which implement that interface can be passed in. But there is no way to require an interface be what is passed in because you can't create them.
I think you need to rethink what you're trying to accomplish.
You're making a distinction between the type of the object (in this case A) and the type of the reference to the object (in this case ISomething).
Sounds like you want to permit this code:
ISomething something = new A();
MyClass.register(something);
but forbid this code:
A something = new A();
MyClass.register(something);
I don't think you can achieve this with Java.
Let me see if I understand.
Do you want to check at compile time that the argument passed to a function is some interface? Any interface?
If that's the question, the answer is you can't.
I don't know which interface I'm going to get [...] I need the real interface.
You can't actually validate if you don't know which type to expect.
In Java you need to know the type to validate the parameter, the argument must be of the same type or a descendant, Java doesn't make distinctions on this regard at compile time, you can make it at runtime as Daff aswered.
You can ask the class of the object you get interfaces it implements during runtime.
If you can't already give the compiler the types of the interfaces you expect it has no way to predict what is going to be passed into your method so you will have to use runtime reflection.
There's no way to check at runtime, if the 'object is an interface' because an object can never ever be 'an interface', it only be an instance of a class that implements an interface.
And it's not possible to restrict a method signature to interface usage, say you'll allow type 'Animal' but not type 'Dog' which implements animal behavior. (I guess that's what you were looking for)
Taking your example - you want a compiler error for this implementation:
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here
But practically spoken - I see no immediate reason. If you want to enforce programmers to use interfaces - user code inspection or quality check tools. If you want to restrict instantiation of an implementation, protect the constructor and use a factory to produce instances.
"The object is an interface" doesn't make sense. It seems like you want to enforce that the pointer passed into the function was declared with an interface type like
Interface_t x = new Class_which_implements_interface_t();
as opposed to
Class_which_implements_interface_t y = new Class_which_imlements_interface_t();
The only problem is that if you make a function like this:
void some_func(Interface_t z) {...}
And you call it with some_func(x); or some_func(y); the function is passing the reference by value, which means that inside of some_func, z is a copy of x or y which has been casted to an Interface_t pointer. There is no way to get information about what type the original pointer had. As long as it is able to be casted to an Interface_t it will compile and run.