简体   繁体   中英

how to call a method with an Object parameter instead of the actual parameter type in java?

Hello everyone i just want to know how can we call a method passing an object type as parameter instead of the actual parameters.Suppose i have a class

public class Helper {

    public void showEntity(Message msg)
    {
        System.out.println(msg.sessionID);
    }

}

now i want to call showEntity Method but i only have information about the name of the parameter's type ie Message naturally i'll create an object of this class by using Class.forName().getClass and then will create a new instance and all that.

Class<?> clazz=Class.forName(nameOfParameterType).getClass();
Object obj=clazz.newInstance();

Now the question arises how will i actually call the showEntity method by passing in the created Object type instead of the actual Message Type beacuse calling showEntity(obj) gives error and i dont want to use reflection to cal this method i want to do it via

Helper helper=new Helper();
helper.showEntity(obj) //gives error 

The simple answer is: by casting, like (Message) thatObjThatIsAMessage . Or, by using reflection to invoke that method (which would of course only add madness here).

The real answer is: you are going down the very wrong rabbit hole.

You do not invoke methods and pass arbitrary parameters because you can. You do that because you need to.

If you don't know what parameter to pass to a method, why do you think you should invoke that method in the first place? That is like "I don't know what is happening when dialing 911 (or whatever your emergency number is), but I have a phone in front of me, so I will do that now".

And of course: the fact that you then consider to use reflection just adds to that. Reflection and doing things byName() is something you absolutely only do when you don't have any other choice! Who says for example that your Message class has a no-argument constructor, so that newInstance() would actually work out?! What if it has one today, but the person owning it removes that tomorrow. You will only learn that at runtime! This is not meant to belittle you, but honestly: a person who does not know how to cast an object, that person is lacking basic Java knowledge. Reflection is completely beyond what you should be dealing with at that skill level.

Long story short: stop right now, and determine what you really have and want to do. I guarantee you: it is not to call a method you don't have appropriate parameters for!

I am not sure if I am missing something, but you can just cast it. That should work fine in case you are certain the type can only be Message:

helper.showEntity((Message)obj);

I would just for sake of code-quality add some kind of check before that call and throw IllegalArgumentException in case type is not Message.

1) Don't do clazz.newInstance(); but do clazz.getConstructor().newInstance(); to ensure to trap any checked exception.

2) Never write such a code : helper.showEntity((Message)obj); .
A best idiom is to cast as assignment to newInstance() in order to centralize the instantiation/cast logic and its exceptions:

Class<?> clazz = ...;
try {
    Messsage message = (Message) clazz.getConstructor().newInstance();
    // do something with message

} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException | ClassCastException e) {
    // handle the exception
}

3) Favor Supplier to reflection when you can.
If the class is defined at compile time somewhere and here it seems to be the case since you expect a specific class ( Message ), you should do something like that :

Helper helper=new Helper();
helper.showEntity(getNewMessage().get());

Supplier<Message> getNewMessage(){
   return Message::new;
}

helper.showEntity((Message)obj) //gives error - you need a cast

Runnable version:

public class SO {


public static class Helper {
    public void showEntity(Message msg) {
        System.out.println(msg.sessionID);
    }
}

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

    Class<?> clazz= Class.forName(Message.class.getName());
    Message msg = (Message) clazz.newInstance();
    msg.sessionID = UUID.randomUUID().toString();
    new Helper().showEntity(msg);// here the instance is cast to Message and should work.

}

One option as following. In this case the type you can pass to showEntity is restricted to type Message and its sub classes which i think should be the case, else you will not know how to get an instance of the object and which method to call as you are not open of reflection APIs. Having no knowledge of what type is being passed calls for usage of reflection APIs.

public class Helper {

    public void showEntity(String msgImpl) {
        try {
            System.out.println(getMessageInstance(msgImpl).getSessionId());
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private Message getMessageInstance(String msgImpl)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Class<? extends Message> msg = Class.forName(msgImpl).asSubclass(Message.class);
        return msg.newInstance();
    }

    public static void main(String[] args) {
        Helper h = new Helper();
        h.showEntity("com.foo.Message");
    }
}

public class Message {

    public String getSessionId() {
        return "SessionID";
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM