【问题标题】:Reflection: cast an object to subclass without use instanceof反射:将对象强制转换为子类而不使用 instanceof
【发布时间】:2010-05-06 10:38:41
【问题描述】:

我有这个简单的接口/类:

public abstract class Message {}

public class Message1 extends Message {}

public class Message2 extends Message {}

还有一个实用类:

public class Utility {
    public void handler(Message m) {
        System.out.println("Interface: Message");
    }

    public void handler(Message1 m) {
        System.out.println("Class: Message1");
    }

    public void handler(Message2 m) {
        System.out.println("Class: Message2");
    }
}

现在,主要课程:

public static void main(String[] args) {

    Utility p = new Utility();

    Message1 m1 = new Message1();
    p.handler(m1);

    Message m = (Message) m1;
    p.handler(m);

}

输出是

> Class: Message1
> Interface: Message

我希望p.handler(m) 调用方法p.handler(m:Message1)

我不想使用“手动”命令instanceof,因为我有很多案例:

if(m instance of Message1)
p.handler((Message1)m)
else if (m instanceof Message2)
p.handler((Message2)m)
...

如果我调用m.getClass(),我会获得“mypackage.Message1”,所以是子类而不是超类。

我尝试使用这段代码(使用反射):

p.handler(m.getClass().cast(m));

但是输出是

> Interface: Message

所以,这是我的问题。我会在不使用“代码命令” istanceof 的情况下将超类对象运行时转换为子类对象。

我想要这样一个正确的命令:

p.handler((m.getclass)m);

我怎样才能获得它?有可能吗?

【问题讨论】:

  • 请清理格式!您已将代码格式化为代码、块引用和正文。
  • "我希望 p.handler(m) 调用方法 p.handler(m:Message1)" -- 这不是 Java 的工作方式! Java 是单一调度的!
  • 由 rsp 回答 - 顺便说一句,根据我的经验,方法重载在 Java 中经常被滥用。容易出现问题,特别是对于这里的类/子类重载。仅在需要或增加一些价值时使用它。有些人在不需要的情况下使用重载,认为它有点优雅。它不是。 stackoverflow.com/questions/248222/…

标签: java reflection subclass instanceof superclass


【解决方案1】:

Java 将根据编译时已知的信息调用该方法。您可以做的是向接口添加一个方法,为该对象调用正确的处理程序方法。

public abstract class Message {

    public abstract void callHandler(Utility utility);

}

public class Message1 extends Message{

    public void callHandler(Utility utility) {
        utility.handler(this);
    }
}

您对处理程序的调用变为:

Message m=(Message) m1;
m.callHandler(p);

它现在调用 Utility::handler(Message1),即使 main 中的引用是 Message 接口的类型。

【讨论】:

  • @rsp:在Message的callHandler方法中添加'abstract'关键字。
  • 也许值得指出的是,这种技术通常被称为“多次调度”,是“访问者”设计模式背后的基本原则。
【解决方案2】:

我不确定您的 handle(..) 方法应该做什么,但由于它们依赖于 Message 的特定实例,您应该考虑将 handle() 方法添加到您的 Message 类(作为抽象方法)。这样,每条消息都实现了自己的句柄版本,您可以享受多态的好处:

Message m = new Message1();
m.handle();

此代码将根据需要返回“Class: Message1”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 2011-02-02
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 2012-05-30
    相关资源
    最近更新 更多