Java您能在Java中使预定义类可序列化吗?

Java您能在Java中使预定义类可序列化吗?,java,serialization,Java,Serialization,我想用java通过网络发送一个图像对象 我得到这个错误 java.io.WriteAbortedException:写入中止;java.io.NotSerializableException:sun.awt.image.OffScreenImage java Image对象未实现可序列化。有没有办法绕过这个问题 我已经尝试过创建image的子类并实现它,但是在使用createImage方法时出现了错误。谢谢你的帮助 编辑* 好的,这是代码,但是有很多。该计划的想法是它是一个象形游戏。有人可以使用

我想用java通过网络发送一个图像对象

我得到这个错误

java.io.WriteAbortedException:写入中止;java.io.NotSerializableException:sun.awt.image.OffScreenImage

java Image对象未实现可序列化。有没有办法绕过这个问题

我已经尝试过创建image的子类并实现它,但是在使用createImage方法时出现了错误。谢谢你的帮助

编辑*

好的,这是代码,但是有很多。该计划的想法是它是一个象形游戏。有人可以使用基本工具绘制,它会通过网络发送,并在其他客户端屏幕上绘制该图像

这是我的基本绘图区域,用户可以在其中使用线条工具进行绘制。释放鼠标后,它将尝试将图像对象发送到服务器

class PadDraw extends JComponent {
    Image image;
    Graphics2D graphics2D;
    int currentX, currentY, oldX, oldY;
    int lineSize = 1;

    public PadDraw() {
        setDoubleBuffered(false);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                oldX = e.getX();
                oldY = e.getY();
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                currentX = e.getX();
                currentY = e.getY();
                //graphics2D.drawLine(oldX, oldY, currentX, currentY); //this is where it does the drawing
                //It seems to draw a line between the old coordinate point and the new coordinate point rather than drawing it as points
                //Test to see if I can get a drawoval to work rather than a line
                //graphics2D.fillOval(currentX-1, currentY-1, 2, 2);
                //if this works it should draw an oval at the cursor position rather than drawing a line
                //technically it works, but without a line it causes gaps
                //I may have found it.  Testing the setStroke method
                graphics2D.setStroke(new BasicStroke(lineSize));
                graphics2D.drawLine(oldX, oldY, currentX, currentY);    
                repaint();
                oldX = currentX;
                oldY = currentY;
            }
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                try {
                    clientOutputStream.writeObject(image);
                } catch (IOException ex) {
                    Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        if (image == null) {
            image = (Image) createImage(getSize().width, getSize().height);
            graphics2D = (Graphics2D) image.getGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            clear();
        }
        g.drawImage(image, 0, 0, null);
    }

    public void updateImage(Image image){
        this.image = image;
        repaint();
    }

    public void clear() {
        graphics2D.setPaint(Color.white);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        //graphics2D.setPaint(Color.BLACK);
        lineSize = 1;
        repaint();
    }

    public void fill(){
        Color c = findColor();
        graphics2D.setPaint(c);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        repaint();
    }

    public void changeColor(Color theColor) {
        graphics2D.setPaint(theColor);
        repaint();
    }

    public Color findColor() {
        return graphics2D.getColor();
    }

    public void changeSize(int size) {
        lineSize = size;
    }
}
public void run2() throws IOException, ClassNotFoundException, InterruptedException {
    // Make connection and initialize streams
    serverAddress = getServerAddress();
    Socket socket2 = new Socket(serverAddress, 9999);
    //String theIP = getIP();
    //Socket socket2 = new Socket(theIP, 9999);
    // Process all messages from server, according to the protocol.
    clientOutputStream = new ObjectOutputStream(socket2.getOutputStream());
    clientInputStream = new ObjectInputStream(socket2.getInputStream());
    while (true) {
        Image ni = (Image)clientInputStream.readObject();
        drawPad.updateImage(ni);
    }
}
这是服务器上映像的线程类

private static class Handler2 extends Thread {
    private Socket socket1;
    private ObjectInputStream serverInputStream;
    private ObjectOutputStream serverOutputStream;
    public Handler2(Socket sock1) {
        socket1 = sock1;
    }

    @Override
    public void run() {
        Image image = null;
        try {
            serverInputStream = new ObjectInputStream(socket1.getInputStream());
            serverOutputStream = new ObjectOutputStream(socket1.getOutputStream());
            oos.add(serverOutputStream);
            while (true) {
                image = (Image)serverInputStream.readObject();
                for (ObjectOutputStream ooss : oos) {
                    ooss.writeObject(image);
                }
            }
        } catch (IOException e) {
            System.out.println(e);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (serverOutputStream != null) {
                oos.remove(serverOutputStream);
            }
            try {
                socket1.close();
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }
}
回到客户端,我有一个从服务器获取图像的方法

class PadDraw extends JComponent {
    Image image;
    Graphics2D graphics2D;
    int currentX, currentY, oldX, oldY;
    int lineSize = 1;

    public PadDraw() {
        setDoubleBuffered(false);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                oldX = e.getX();
                oldY = e.getY();
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                currentX = e.getX();
                currentY = e.getY();
                //graphics2D.drawLine(oldX, oldY, currentX, currentY); //this is where it does the drawing
                //It seems to draw a line between the old coordinate point and the new coordinate point rather than drawing it as points
                //Test to see if I can get a drawoval to work rather than a line
                //graphics2D.fillOval(currentX-1, currentY-1, 2, 2);
                //if this works it should draw an oval at the cursor position rather than drawing a line
                //technically it works, but without a line it causes gaps
                //I may have found it.  Testing the setStroke method
                graphics2D.setStroke(new BasicStroke(lineSize));
                graphics2D.drawLine(oldX, oldY, currentX, currentY);    
                repaint();
                oldX = currentX;
                oldY = currentY;
            }
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                try {
                    clientOutputStream.writeObject(image);
                } catch (IOException ex) {
                    Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        if (image == null) {
            image = (Image) createImage(getSize().width, getSize().height);
            graphics2D = (Graphics2D) image.getGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            clear();
        }
        g.drawImage(image, 0, 0, null);
    }

    public void updateImage(Image image){
        this.image = image;
        repaint();
    }

    public void clear() {
        graphics2D.setPaint(Color.white);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        //graphics2D.setPaint(Color.BLACK);
        lineSize = 1;
        repaint();
    }

    public void fill(){
        Color c = findColor();
        graphics2D.setPaint(c);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        repaint();
    }

    public void changeColor(Color theColor) {
        graphics2D.setPaint(theColor);
        repaint();
    }

    public Color findColor() {
        return graphics2D.getColor();
    }

    public void changeSize(int size) {
        lineSize = size;
    }
}
public void run2() throws IOException, ClassNotFoundException, InterruptedException {
    // Make connection and initialize streams
    serverAddress = getServerAddress();
    Socket socket2 = new Socket(serverAddress, 9999);
    //String theIP = getIP();
    //Socket socket2 = new Socket(theIP, 9999);
    // Process all messages from server, according to the protocol.
    clientOutputStream = new ObjectOutputStream(socket2.getOutputStream());
    clientInputStream = new ObjectInputStream(socket2.getInputStream());
    while (true) {
        Image ni = (Image)clientInputStream.readObject();
        drawPad.updateImage(ni);
    }
}
我知道我的代码有点糟糕。我花了很多时间来测试各个部件。和网络代码一样收费。它应该会起作用。我认为唯一的问题是它不可序列化

java Image对象未实现可序列化。有没有办法绕过这个问题


您可以自己序列化它。你可以用一个可外部化的类来包装它,也可以不用writeObject在映像中写入数据。

简单回答:不。
sun.awt.image.OffScreenImage
并不意味着要直接序列化,所以你不能只在子类上添加
Serializable
接口来使其可序列化

你必须找到解决办法,我不确定这张图片是关于什么的,但是,例如,如果它来自一组已知的图片,那么你可以通过网络向它发送一个密钥,这样你就可以在另一端恢复它。如果您需要直接传递图像数据,那么您必须将其封装在另一个对象中,并在另一侧重建OffScreenImage


您可以通过一些工作扩展该类并使其可序列化,但由于它似乎是一个与操作系统紧密耦合的类,因此需要一些思考。

请包含您尝试过的代码。