Dynamically load a class in java - java

Here is my classes.
package com.psu.janibot;
public class Janibot implements Runnable {
public void move() {
System.out.println("move");
}
#Override
public void run() {
}
// main method
public static void main(String[] args) {
try {
Janibot janibot = (Janibot) Class.forName("Janitor").newInstance();
janibot.run();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
import com.psu.janibot.Janibot;
public class Janitor extends Janibot {
public void run() {
move();
}
}
package com.psu.janibot;
public class Janitor2 extends Janibot{
public void run() {
move();
}
}
if i type >java Janitor it will run the Janitor class
if i type >java Janitor2 it will run the Janitor2 class
I want to do is to run Janitor or Janitor2 without typing the class name in forName method like this Janibot janibot = (Janibot) Class.forName("Janitor").newInstance();

Class.forName() takes a String as a parameter, so you need to pass it somehow, so I presume you mean not hard coded.
Pass the String in as the arguments to the program and read them from the args array
java Janibot Janitor
....
Class.forName(args[0]).newInstance()
Other options exist such as read from file, using a Scanner, etc.

Related

Java Reflection : Initialize object using interface but using String value for class name

Lets say I have the following setup
an interface
public interface TestInterface {
public void draw();
}
and two implementations
public class Square implements TestInterface {
#Override
public void draw() {
System.out.println("Square");
}
}
and
public class Circle implements TestInterface {
#Override
public void draw() {
System.out.println("Circle");
}
}
Now I can easily do
TestInterface a = new Square();
a.draw();
and I correctly get Square. Next, I wanted to try out reflection.
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Constructor<?> constructor = null;
try {
constructor = clazz.getConstructor();
} catch (NoSuchMethodException | SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Object instance = null;
try {
instance = constructor.newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method method = null;
try {
method = instance.getClass().getMethod(methodName);
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
method.invoke(instance);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
and for className as some.package.Square and methodName as draw I again get Square. Which is correct.
The problem is that my application has access to the interface but not the actual implementations. Hence I know which methods to invoke, but I have to specify the implemented classes as well and I dont know which package they may reside in. What if I only know the name of the class but not the package?
Is there a way where I can still use the initialization form of
TestInterface a = new <some_parameter>();
a.draw();
Is there a way to generalize it? Or is the approach using reflection that I showed above, the only way to achieve something like this? Lastly, would it make any difference if I used an abstract class instead of an interface?
You need to pass:
#param className the fully qualified name of the desired class.
When you have for example three class with the Same name but in diferent packages
--package1
----Test
--package2
----Test
Main
Test
And in Main you have:
public static void main(String[] args) throws UnsupportedEncodingException {
Class<?> clazz = null;
try {
clazz = Class.forName("Test");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It will call the one that is level of Main. For calling the others you will need to pass the fully quallifed name.
clazz = Class.forName("package1.Test");
clazz = Class.forName("package2.Test");
What if I only know the name of the class but not the package? So you need to know in what level you want. Because as you know that different packages the classes can have same names. So which Class do you need if you have that issue.
You have to know the full name of the class. Only the name of the class is not enough to load it in the memory and to use it through reflection. However, you can determine the implementations of your interface using the reflections library.
Maybe this discussion thread can help you: How can I get a list of all the implementations of an interface programmatically in Java?

I can't mock static method using Mockito and PowerMockito

I'm having trouble mocking a static method in a third-party library. I keep receiving a null-pointer exception when running the test, but I'm not sure why that is.
Here is the class and the void method that invokes the static method I'm trying to mock "MRClientFactory.createConsumer(props)":
public class Dmaap {
Properties props = new Properties();
public Dmaap() {
}
public MRConsumerResponse createDmaapConsumer() {
System.out.println("at least made it here");
MRConsumerResponse mrConsumerResponse = null;
try {
MRConsumer mrConsumer = MRClientFactory.createConsumer(props);
System.out.println("made it here.");
mrConsumerResponse = mrConsumer.fetchWithReturnConsumerResponse();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return mrConsumerResponse;
}
}
Below is the test that keeps returning a null-pointer exception. The specific line where the null-pointer is being generated is: MRClientFactory.createConsumer(Mockito.any(Properties.class));
#RunWith(PowerMockRunner.class)
#PrepareForTest(fullyQualifiedNames = "com.vismark.PowerMock.*")
public class DmaapTest {
#Test
public void testCreateDmaapConsumer() {
try {
Properties props = new Properties();
PowerMockito.mockStatic(MRClientFactory.class);
PowerMockito.doNothing().when(MRClientFactory.class);
MRClientFactory.createConsumer(Mockito.any(Properties.class));
//MRClientFactory.createConsumer(props);
Dmaap serverMatchCtrl = new Dmaap();
Dmaap serverMatchCtrlSpy = spy(serverMatchCtrl);
serverMatchCtrlSpy.createDmaapConsumer();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Please follow this example carefully: https://github.com/powermock/powermock/wiki/MockStatic
Especially you are missing a
#PrepareForTest(Dmaap.class)
…to denote the class which does the static call.

Reflection of hide interface

How can i call registerAudioPortUpdateListener?
I succeeded to call a hidden function.
But, in this situation i need to call a function with hidden inner interface as parameter.
public class AudioManager {
/**
* Listener registered by client to be notified upon new audio port connections,
* disconnections or attributes update.
* #hide
*/
public interface OnAudioPortUpdateListener {
/**
* Callback method called upon audio port list update.
* #param portList the updated list of audio ports
*/
public void onAudioPortListUpdate(AudioPort[] portList);
/**
* Callback method called upon audio patch list update.
* #param patchList the updated list of audio patches
*/
public void onAudioPatchListUpdate(AudioPatch[] patchList);
/**
* Callback method called when the mediaserver dies
*/
public void onServiceDied();
}
/**
* Register an audio port list update listener.
* #hide
*/
public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
sAudioPortEventHandler.init();
sAudioPortEventHandler.registerListener(l);
}
}
Can you try this code , for me it is working in java,
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import de.apps.io.AudioManager;
public class Application {
public static void main(String[] args) {
System.out.println("hello world");
Class someInterface1 = null;
try {
// someInterface = AudioManager.class.getDeclaredClasses();
someInterface1 = Class.forName("de.apps.io.AudioManager$OnAudioPortUpdateListener");
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println(someInterface);
System.out.println(someInterface1);
Object o = Proxy.newProxyInstance(someInterface1.getClassLoader(), new java.lang.Class[] { someInterface1 }, new Handler());
AudioManager manager = new AudioManager();
Method me = null;
try {
me = manager.getClass().getMethod("registerAudioPortUpdateListener", new java.lang.Class[] { someInterface1 });
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
me.invoke(manager, o);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(me);
}
static class Handler implements InvocationHandler
{
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String method_name = method.getName();
Class<?>[] classes = method.getParameterTypes();
System.out.println("called " + method_name);
return null;
}
}
}

Get class from bounded type

I'm learning java generics and I don't know the right way to accomplish this problem.
I have a Bean class:
public class Bean<C> {
protected Dao<C, Integer> getDao(Context context)
{
Dao<C, Integer> dao;
try {
dao = DatabaseHelper.getInstance(context).getDao(); //HERE
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The method getDao() expects as argument a Class<T>. When I simply place the C type, it doesn't work (even with C.class).
What should I do?
Thanks.
Problem solved with another parameter on my method:
protected Dao<C, Integer> getDao(Context context, Class<C> clazz)
{
Dao<C, Integer> dao;
try {
dao = DatabaseHelper.getInstance(context).getDao(clazz);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Java reflection method invoking error

I'm making a kind of test program to be able to override methods in classes for an api I'm making in java but I'm getting a weird error when trying to invoke a method from another class...
Here is the main "component class":
package st.cmp;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Component {
public class Overrider{
Class<?> source;
Class<?>[] overs;
String name;
public Overrider(Class<?> s,String n,Class<?>[] o){
source=s;
overs=o;
name=n;
}
public Object call(Object[] param){
try {
return source.getMethod(name, overs).invoke(this, param);
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
};
public HashMap<String,Component> cmps;
public HashMap<String,Overrider> over;
public Component(){
cmps=new HashMap<String,Component>();
over=new HashMap<String, Overrider>();
}
public void registerComponent(String nm,Component cm){
cmps.put(nm,cm);
}
public Component getComponent(String nm){
return cmps.get(nm);
}
public void override(Class<?> cl,String name,Class<?>[] param){
over.put(name,new Overrider(cl,name,param));
}
public Object call(String mnm,Object[] a){
Overrider ov=over.get(mnm);
if(ov!=null){
ov.call(a);
}
Class<?>[] abc=new Class<?>[a.length];
for(int i=0;i<a.length;i++){
abc[i]=a[i].getClass();
}
try {
return this.getClass().getDeclaredMethod(mnm, abc).invoke(this,a);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException
| SecurityException e) {
// TODO Auto-generated catch block
try {
this.getClass().getDeclaredMethod(mnm, abc).invoke(this,a);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException
| SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
public void test(String a){
System.out.print(a);
}
public int add(Integer a,Integer b){
return a+b;
}
}
And this is the main class:
package st;
import st.cmp.Component;
public class Start {
public static void main(String[] args)
{
new Start().start();
}
public void start(){
Component a=new Component();
a.call("test",new Object[]{a.call("add",new Object[]{1,5}).toString()});
a.override(this.getClass(), "add", new Class<?>[]{Integer.class,Integer.class});
a.call("test",new Object[]{a.call("add",new Object[]{1,5}).toString()});
}
public int add(Integer a,Integer b){
return a*b;
}
}
I'm getting this error when I start the program:
6java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at st.cmp.Component$Overrider.call(Component.java:22)
at st.cmp.Component.call(Component.java:64)
at st.Start.start(Start.java:16)
at st.Start.main(Start.java:8)
6
Can anyone help me?
it says "object is not an instance of declaring class"... But what "object" is it refering to?
In your Start class, you are calling the Component.override() method:
// v--- This is the Class Object
a.override(this.getClass(), "add", new Class<?>[]{Integer.class,Integer.class});
Where a is of type Component. You are passing it this.getClass(), which is a Class object for Start. Then in override():
// v--- Class object gets passed along here
over.put(name,new Overrider(cl,name,param));
You are creating a new Overrider, and giving the Class object for Start to the constructor, which sets the Class<?> source; field to the Start Class object. Then when you call the Overrider.call() method, it does this:
// v--- and finally invoked here
return source.getMethod(name, overs).invoke(this, param);
And passes invoke() a this which is an instance of Component, while source is a Class object for Start. In this line, "source" and "this" need to be the same class, but Start and Component aren't.
Your code is quite convoluted, but this my help. If you have a line like this:
klass.getMethod(name).invoke(obj)
then the error says that obj is not an instance of klass.

Categories

Resources