是否可以通过RMI中的引用传递?

我已经阅读了有关使用RMI传递变量的各种文章。

他们中的一些人说,通过RMI中的引用传递变量是不可能的。 例如: 这一个和这一个

而其他人说这是可能的。 例如: 这一个 , 这个和这一个

任何人都可以清楚这一点吗? 🙂

重要说明:如果通过引用传递意味着修改方法内的参数值并更改调用者中的原始变量,则不能。 如果您要做的是将引用的副本传递给对象,以允许该方法与您的某个对象进行交互…是的,您可以。 答案探讨了第二种选择。

是。 但它必须是一个RMI对象。 在这种情况下,RMI存根将通过副本传递。

RMI以两种方式传递参数和返回值:

  1. 复制完整的对象
  2. 发送一个远程引用(如果它是引用它必须是远程引用!)。

样品

猜猜我们有服务。 它是一个RMI对象,通过RMI注册表发布,因此可以访问客户端。 客户端可以在其上调用一个方法(创建一些东西),服务想要返回对新创建的对象的引用。 不是序列化副本,而是对服务器内存空间中创建的对象的引用。

import java.rmi.Remote; import java.rmi.RemoteException; // normally published object public interface MyService extends Remote { // creates something and return a "handle" to it public MyHandle createX(SomeSerializableObj param1) throws RemoteException; } // interface for object that the service will return a reference to... public interface MyHandle extends Remote { void doOne(); void doTwo(); } 

在这个例子中你可以:

创建MyService的实现并发布它

 Registry registry = LocateRegistry.createRegistry(port); MyService stub = (MyService) UnicastRemoteObject.exportObject(server, 0); registry.bind("myService", stub);` 

然后,一些RMI客户端可以获得它的引用

 Registry registry = LocateRegistry.getRegistry(server, port); MyService serv1 = (MyService) registry.lookup("myService"); 

并且对服务对象的引用可以获得对其他RMI对象的引用。

 MyHandle handle1 = serv1.createX(...); handle1.doOne() 

在此示例中,方法参数是序列化的(它应该是Serializable类),而返回的对象是对服务器中创建的对象的RMI引用。

createX(…)的实现可能是:

 public MyHandle createX(...) { MyHandle handle = new MyHandleImpl(); // create an implementation createdHandlers.add(handle); // add it to some structure (just a sample) return handle; // return the implementation. RMI will send to client a RMI reference to this very instance } 

你的参考资料:

(1)说RMI不支持通过引用传递。 我同意。

(2)表示RMI不支持输入输出参数。 我同意。

(3)只是表现出通过引用传递和通过值传递引用之间的通常混淆。 RMI就像Java的其他部分一样完成后者。

(4)错了。

(5)只是简单的语无伦次。 RMI中没有传递引用。

除了可能的其他故障模式之外,RMI的远程“按值引用”在本质上与Java的本地“按值引用”在语义上没有区别。

您所读取的含义是,对于非远程引用,RMI对象参数和结果通过传递通过对象序列化,而不是通过Java的参数传递方法按值引用。

在最真实的意义上,你不能。

当您通过“引用”传递某些内容时,您实际在做的是将指针传递给内存中的某个位置。 当调用者和被调用者是相同的进程时,它可以完美地工作,他们可以访问完全相同的堆。 但是将内存引用从计算机A传递到计算机B是没有意义的,A无法访问Bs内存*。

但是,RMI允许您获取远程对象的“引用”,但这不完全相同,并且必须提前请求,将您的一个对象传递给服务器将产生副本。

直接从马口(http://www.oracle.com/technetwork/java/javase/tech/index-jsp-138781.html#3)

RMI使用标准Java对象序列化机制来传递对象。 引用远程对象的参数作为远程引用传递。 如果方法的参数是基本类型或本地(非远程)对象,则会将深层副本传递给服务器。 返回值以相同的方式处理,但在另一个方向上。 RMI允许您传递和返回本地对象的完整对象图以及对远程对象的引用。

您可以通过引用传递远程对象,但不能将本地对象作为引用传递回服务器。

*技术上在一些大型分布式共享内存系统中你可以,但我怀疑这是OP正在谈论的内容。