3

我正在根据RAW 套接字实现肯定确认和重传传输协议,在这种情况下需要一个子类。在实现方法时,我需要这样的东西:SocketImplaccept

protected void accept(SocketImpl s) {
    ...
    s.copy(socket);
}

哪里是一个必须复制到已经初始化的对象socket的已经计算的对象。即我需要一个可变的复制方法,它将源复制到目标。我知道存在,但它返回一个新对象,我需要的是 mutate 。SocketImpl SocketImpls s.copy(socket)socketsObject clone()s

顺便说一句,你们中的一些人认为在这种情况下改变s参数是一个错误的设计。它不是 Java 标准库中的唯一示例。implAccept(Socket s)ServerSocket是另一个例子。但这就是 Sun/Oracle 工程师设计它的方式。我想知道为什么这是一个糟糕的设计

乍一看,提供一个通用的 shallow target.copy(source)wheretarget = souce.clone()相当于target = new TheClass(); target.copy(source);似乎是有道理的。但由于它不存在(可能有充分的理由,请解释)唯一的方法是编写一个自定义的逐字段复制方法

我对吗?谢谢。

4

2 回答 2

1

您误解了此方法的用途和工作原理。我已经做过很多次了。SocketImpl提供给implAccept()新接受的套接字,而不是ServerSocket. 所以你不需要第二个副本。您需要做的就是将其包装SocketImplSocket. 或您自己的派生类中SocketSocket奇怪的是,甚至为此目的提供了一个构造函数。

于 2012-10-25T22:48:29.137 回答
0

我想没有标准target.copy(source)(即可变复制方法),因为它比克隆更少需要:

  • 您需要单独决定(针对您的情况和所有领域),它们是否应该被复制或相同(就像克隆与深度克隆一样);
  • 您通常可以进行设计,以便您只需切换您在外部持有的引用,因此在您的情况下,您可以切换为使用引用s而不是到处使用当前对象,这更简单,更有效。如果您需要复制值,这对应于克隆(或使用复制构造函数);
  • s您可以通过包装参数(在您的情况下为对象)轻松实现它。

最后一点也回答了您的第二个问题:除了逐字段复制之外,您还可以实现一个转发类,将 SocketImpl 的所有导出方法转发到包装的核心 SocketImpl:

  • 使用你当前的实现类C作为私有实现,protected void accept(SocketImpl s)只抛出一个异常;
  • 编写一个转发D
    • 包装一个 SocketImpl(例如 的对象C),保存在私有字段中wrapped
    • 扩展 SocketImpl 并转发其所有方法,acceptwrapped
    • 用;¹protected void accept(SocketImpl s)简单地实现{ s.wrapped = this; }
  • 如果您希望在某些情况下复制所有字段,请提供accept一个复制的参数,例如 via accept(s.clone())accept如果您希望在所有情况下都复制,则可以在其中复制);
  • 只给出类型的对象D,这样C就不会抛出异常。

¹ 此实现accept仅适用于 类型的参数D。否则,这种可怕的设计(必须改变作为参数给出的 SocketImpl)需要accept使用丑陋的技术,例如反射(参见例如http://www.docjar.com/上的 org.apache.harmony.luni.net.PlainSocketImpl html/api/org/apache/harmony/luni/net/PlainSocketImpl.java.html)。

于 2012-10-25T22:13:31.030 回答