为什么SocketChannels是抽象的?

时间:2015-12-11 20:00:43

标签: java class sockets oop nio

我正在编写基于NIO的套接字服务器。

我认为创建一个扩展NIO SocketChannel类的类是个明智之举,这样我就可以直接在套接字对象中存储自定义信息。

使用java.net.Socket

可以很容易
public class Session extends Socket {
    private Long created = System.currentTimeMillis();
}

但我不能用java.nio.channels.SocketChannel做同样的事情,因为它是一个抽象类。如果我想扩展SocketChannel,我需要编写一堆方法。

据我所知,抽象类无法实现,因此像ServerSocketChannel.accept()这样的方法实际上必须返回一个扩展SocketChannel的具体类。如果是这样,那叫什么课?如果没有,为什么课程抽象呢?

3 个答案:

答案 0 :(得分:2)

这是您将使用装饰器模式的情况。

public class Session{

    private SelectableChannel channel;
    private Long created = System.currentTimeMillis();

    public Session(SelectableChannel channel){
        this.channel = channel;
    }

    public <T>T getChannel(){
        return (T)channel;
    }

    public long getWhenCreated(){
        return created;
    }
}

你可以这样使用它。

Session session = new Session(DatagramChannel.open());
Session session2 = new Session(SocketChannel.open());

DatagramChannel datagramChannel = session.getChannel();
SocketChannel socketChannel = session2.getChannel();

答案 1 :(得分:1)

最好的办法是创建一个包装器类,它在构造函数中接受SocketChannel并为所有方法调用委托它。您需要实现SocketChannel的所有方法,但您只需将这些调用委托给SocketChannel,并在这些调用之前或之后添加您需要的任何其他功能。

答案 2 :(得分:1)

是的,就是这样。 Javadoc没有说明实际实例化的具体类,然后它必须是私有的或包私有的,所以从外面看不到它。首先想到的是,实现是特定于平台的(通过JNI调用特定的OS原语),但不添加任何额外的方法。这只是一个假设,我从未见过源代码。

但是,您可以通过继承和组合轻松扩展类。您的实现只会将对方法的调用转发到您在派生类中作为私有成员持有的具体对象。