【问题标题】:javac claims that I'm not overriding a method in an abstract class implementation when I clearly amjavac 声称我没有在抽象类实现中重写方法,而我显然是
【发布时间】:2010-07-08 01:45:02
【问题描述】:

我会尽量简明扼要,但这是一个复杂的问题。我在 Linux 平台上用 Java 编写,不惜一切代价。

目标的简短版本:我想要一个名为Client 的抽象类,它充当客户端连接的通用容器。 Client 应该线程化它的每个连接。我还有一些经过半测试的代码,它们以类似的编码方式播放服务器对应的代码。抽象的Client 应该被实现为更具体和可实例化的东西。就我而言,我有一个名为FileClientGui 的类,它扩展了Client,并使用从服务器接收文件内容并显示它们的基本方法覆盖了Client 的所有抽象方法。抽象 Client 本身就是 java.lang.Thread 的扩展,这一事实使情况更加复杂。

这是我的通用文件结构:

/class/path/lib/client/Client.java

/class/path/com/fileclient/FileClientGui.java

这两个文件都引用了其他几个自定义类,但我没有从中得到任何错误。如果我需要发布这些项目的代码,请告诉我,我会发布它们。

所以我在终端上运行这个长 javac 命令,设置类路径和构建目录以及所有需要编译的相关文件。我收到的任何代码的唯一错误是:

com/fileclient/FileClientGui.java:26: com.fileclient.FileClientGui is not abstract and does not override abstract method cleanClients() in lib.client.Client

我的代码(见下文)清楚地实现了 Client.java 中定义的方法和所有其他抽象方法。我搜索了互联网,似乎大多数遇到此错误的人都在尝试执行诸如实现 ActionListener 之类的操作,并且对该实现感到困惑,而且很多时候,这只是一个简单的拼写或大写问题。我一遍又一遍地检查我的代码,以确保这不是一个简单的“糟糕”问题。我怀疑这实际上是我的类的名称和其他一些类的名称之间的某种冲突,以某种方式最终出现在我的类路径或 Java 的本机框架/库中,但我找不到任何明显的东西。

无论如何,这是我的代码。

Client.java:

package lib.client;

import lib.clientservercore.Connection;
import lib.simplefileaccess.Logger;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.lang.Thread;

/**
 *
 * @author Ryan Jung
 */
public abstract class Client extends Thread {

    ArrayList<Connection> connections;
    boolean isRunning;
    Logger log;

    public Client (String logFile) {
        log = new Logger(logFile);

        log.write("Initializing client...");
        
        connections = new ArrayList<Connection>(50);

        log.write("Client initialized.");
    }
    
    public void logOut(String contents) {
        log.write(contents);
    }
    
    public Logger getLogger() {
        return this.log;
    }
    
    public ArrayList<Connection> getConnections() {
        return connections;
    }
    
    public void addConnection(Connection c) {
        connections.add(c);
    }
    
    public void removeConnection(Connection c) {
        connections.remove(c);
    }
    
    public boolean getIsRunning() {
        return isRunning;
    }
    
    public void setIsRunning(boolean r) {
        isRunning = r;
    }

    public Connection connect(String host, int port) {
        log.write("Creating new connection...");

        Socket s;
        Connection c = null;

        // Validate port
        if (port <= 1024 || port > 65536) {
            log.write("Invalid server port: " + port + ".  Using 12321.");
            port = 12321;
        }

        try {
            s = new Socket(host, port);
            c = connectClient(s);
        } catch (IOException exIo) {
            log.write("Could not connect to the server at " + host + ":" + port + ".  Exception: " + exIo.getMessage());
            exIo.printStackTrace();
        }

        log.write("Connected client to " + host + ":" + port);
        
        return c;
    }

    @Override
    public void run() {
        log.write("Running client.");
        runClient();
        log.write("Client finished running.");
    }

    abstract Connection connectClient(Socket sock);

    abstract void runClient();

    abstract void cleanClients();

}

FileClientGui.java:

package com.fileclient;

import lib.client.Client;
import lib.clientservercore.Connection;
import lib.clientservercore.Connection.ConnectionStatus;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Iterator;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import java.lang.Thread;

/**
 *
 * @author Ryan Jung
 */
public class FileClientGui extends Client {

    JFrame frmMain;
    JPanel pnlMain;
    JPanel pnlConnect;
    JTabbedPane tabConnections;
    JLabel lblHost;
    JLabel lblPort;
    JTextField txtHost;
    JTextField txtPort;
    JButton btnConnect;

    public FileClientGui(String logFile) {
        super(logFile);

        logOut("Initializing client controller...");

        frmMain = new JFrame("Client");
        pnlMain = new JPanel(new BorderLayout());
        pnlConnect = new JPanel(new FlowLayout());
        tabConnections = new JTabbedPane();
        lblHost = new JLabel("Host:");
        lblPort = new JLabel("Port:");
        txtHost = new JTextField("localhost", 10);
        txtPort = new JTextField("12321", 5);
        btnConnect = new JButton("Connect");

        frmMain.setSize(450, 600);
        frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmMain.add(pnlMain);
        pnlMain.add(pnlConnect, BorderLayout.NORTH);
        pnlMain.add(tabConnections, BorderLayout.CENTER);
        pnlConnect.add(lblHost);
        pnlConnect.add(txtHost);
        pnlConnect.add(lblPort);
        pnlConnect.add(txtPort);
        pnlConnect.add(btnConnect);

        btnConnect.addActionListener(
            new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String host = txtHost.getText();
                    int port = Integer.parseInt(txtPort.getText());
                    try {
                        Socket sock = new Socket(host, port);
                        FileClientConnectionGui c = (FileClientConnectionGui)(connectClient(sock));
                        tabConnections.addTab(c.getInetAddress().toString(), c.getMainPanel());
                    } catch (UnknownHostException ex) {
                        logOut("Can't find host: " + host + ".  Exception: " + ex.getMessage());
                        ex.printStackTrace();
                    } catch (IOException ex) {
                        logOut("Exception: " + ex.getMessage());
                        ex.printStackTrace();
                    }
                }
            }
        );

        frmMain.setVisible(true);

        logOut("Client controller initialized.");

    }

    public void removeConnection(FileClientConnectionGui c) {
        logOut("Removing connection: " + c.getInetAddress().toString());
        tabConnections.remove(c.getMainPanel());
        logOut("Removed connection.");
    }

    Connection connectClient(Socket sock) {
        logOut("Client controller is creating a new connection...");
        FileClientConnectionGui c = new FileClientConnectionGui(sock, getLogger(), this);
        addConnection(c);
        c.start();
        logOut("Client controller created a new connection.");
        return c;
    }
    
    void runClient() {
        setIsRunning(true);
        logOut("Client controller is running.");

        while (getIsRunning()) {
            cleanClients();
            try {
                sleep(500);
            } catch (InterruptedException ex) {
                logOut("Sleep interrupted.  Exception: " + ex.getMessage());
                ex.printStackTrace();
            }
        }

        logOut("Client controller stopped running.");
    }
    
    void cleanClients() {
        Iterator i = getConnections().iterator();
        try {
            while (i.hasNext()) {
                FileClientConnectionGui c = (FileClientConnectionGui)(i.next());
                if (c.getStatus() == ConnectionStatus.CLOSED) {
                    logOut("Removing dead client at " + c.getInetAddress().toString());
                    tabConnections.remove(c.getMainPanel());
                    removeConnection(c);
                }
            }
        } catch (Exception ex) {
            logOut("cleanClients Exception: " + ex.getMessage());
        }
    }

}

我会尽我所能,并提前感谢您提供的任何建议。我对此感到非常困惑。

也许最令人困惑的是(也许这提供了问题的线索?)是我可以注释掉抽象方法的其他实现(例如,runClient 或 connectClient),并且我没有遇到其他问题,只是同一个。此外,如果我像这样将@Override 指令添加到其他指令之一:

@Override
Connection connectClient(Socket sock) {
    logOut("Client controller is creating a new connection...");
    FileClientConnectionGui c = new FileClientConnectionGui(sock, getLogger(), this);
    addConnection(c);
    c.start();
    logOut("Client controller created a new connection.");
    return c;
}

我得到一个额外的错误:

com/fileclient/FileClientGui.java:96: method does not override or implement a method from a supertype

它显然正在覆盖其超类型(即客户端)中的方法。我尝试用完整的类路径 (lib.client.Client) 替换“客户端”,并且根本没有更改任何错误。

我有什么遗漏吗?我没有尝试的东西?

【问题讨论】:

    标签: java methods implementation abstract


    【解决方案1】:

    我相信这是因为您有包级别的抽象方法,这些方法在您的子类中是不可见的。尝试让它们受到保护。

    这里有一对简单的类可以重现问题:

    package x1;
    
    public abstract class P1
    {
        abstract void foo();
    }
    

    然后:

    package x2;
    
    public class P2 extends x1.P1
    {
        void foo() {}
    }
    

    编译它们给出:

    P2.java:3: P2 is not abstract and does not override abstract method foo() in P1
    public class P2 extends x1.P1
           ^
    1 error
    

    在两个类中设置 foo protected 可以解决问题。

    【讨论】:

    • 类不能被声明为受保护,IIRC。您是否建议抽象类将其抽象方法声明为抽象?我会尝试这个并提供结果。感谢您的快速回复。
    • 漂亮!谢谢!在抽象 Client.java 中,我对抽象函数定义进行了保护,在实现 FileClientGui.java 中,我对函数实现进行了保护。代码立即编译,没有错误。我执行了代码并得到了我期望的确切结果。再次感谢。这是正确的答案。
    猜你喜欢
    • 2015-02-28
    • 2023-03-10
    • 1970-01-01
    • 2014-11-24
    • 2015-06-29
    • 2018-09-21
    • 2016-08-13
    • 1970-01-01
    相关资源
    最近更新 更多