我有一个涉及 RMI、序列化和运行时多态性的问题。
我有一个 RMI 服务器,其内容如下:
public interface Shape extends Remote, Serializable {
public double getArea() throws RemoteException;
}
public class Circle implements Shape {
double radius;
public Circle( double r) { radius = r; }
public double getArea() { return Math.PI * radius * radius; }
}
Circle 类的对象 cObj
已在 RMI 注册表中注册:
Circle cObj = new Circle (10);
registry.bind("cObj", cObj);
现在,在客户端,我的 CLASSPATH 上有 Shape.class 文件,但 CLASSPATH 上没有 Circle.class 文件。 RMI客户端可以执行下面的操作吗?
Shape obj = (Shape) registry.lookup("cObj");
obj.getArea();
请注意,Circle.class 不在 RMI 客户端的 CLASSPATH 中,并且客户端上的代码无论如何也不会直接引用 Circle 类。它仅引用Shape接口(interface)类型。
我会如何看待这个问题,可能是客户端执行查找并找到具有 cObj 名称和 Circle 类型的对象。服务器知道 Circle 是 Shape 的子类型,并序列化该对象并将其发送到客户端。现在,我不确定客户端是否可以将其转换为父类(super class)(Shape)类型,而无需访问 Circle 类定义。
感谢帮助。
最佳答案
如果您不想将 Circle 类部署到客户端,您有两种选择:
使用 RMI 代码库功能。您需要查一下这个,因为它是一个太大的主题,无法在这里讨论,但基本上它使得从 RMI 服务器指定的附加位置加载类成为可能。
将其设为导出的远程对象,以便对它的调用也是 RMI 调用。通过将 Shape 扩展为 Remote,您已经完成了一半,但是您还需要导出 Circle,方法是使其扩展 UnicastRemoteObject,或者在构造时使用它调用 UnicastRemoteObject.exportObject()。
在我看来,通过扩展 Remote,你实际上是想一直做 (2)。如果这样做,则不需要使 Shape 扩展可序列化。如果您不执行(2),则让 Shape 扩展 Remote 是没有意义的。您应该删除其中一个:它们是相互排斥的。
关于java - 在 RMI 中将子类对象转换为父类(super class)引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14627840/