【问题标题】:Enum NullPointerException Java枚举 NullPointerException Java
【发布时间】:2020-05-25 16:09:34
【问题描述】:

我正在进行客户端服务器通信,其中一条消息是枚举。为了处理服务器端并使用 .toString() 转换客户端的枚举值,并且在服务器端根据接收到的值,创建的变量获取枚举值。代码是服务器端的,错误在服务器协议上:

if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= 10) {
            return false;
        }

服务端协议代码为:

package Servidor;


import Servidor.TileType;



// Server side protocol

public class ServerProtocol {


    //HighScore HighScore = null;
    //private HighScore hs;
    DataPlayer dataPlayer;// = null;

    private TileType[][] tiles;

    private int lines, score, newLevel, level;

    private static TileType type;



    public ServerProtocol(){

        TileType type = TileType.TypeJ;


    }



    public boolean MsgValidate(String typeS, int x, int y, int rotation) {



        if(typeS == TileType.TypeI.toString()) {
            type = TileType.TypeI;
        } 

        if(typeS == TileType.TypeJ.toString()) {
            type = TileType.TypeJ;
        } 

        if(typeS == TileType.TypeL.toString()) {
            type = TileType.TypeL;
        } 

        if(typeS == TileType.TypeO.toString()) {
            type = TileType.TypeO;
        } 

        if(typeS == TileType.TypeS.toString()) {
            type = TileType.TypeS;
        } 

        if(typeS == TileType.TypeT.toString()) {
            type = TileType.TypeT;
        } 

        if(typeS == TileType.TypeZ.toString()) {
            type = TileType.TypeZ;
        }


        if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= 10) {
            return false;
        }

        if(y < -type.getTopInset(rotation) || y + type.getDimension() - type.getBottomInset(rotation) >= 22) {
            return false;
        }

        for(int col = 0; col < type.getDimension(); col++) {
            for(int row = 0; row < type.getDimension(); row++) {
                if(type.isTile(col, row, rotation) && isOccupied(x + col, y + row)) {
                    return false;
                }
            }
        }
        return true;

    }


    private boolean isOccupied(int x, int y) {
        return tiles[y][x] != null;
    }


}

调用服务器协议的服务器有代码:

package Servidor;

import Servidor.TileType;

public class Server implements Runnable {


    public static final String HighScore = null;
    public Socket server = null;

    private TileType[][] tiles;




    public Server(Socket socket){

        this.server = socket;

    }


    public static void main (String[] args) throws IOException, ClassNotFoundException{

        int port = 6666;

        try(ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port: " + port + "\n\n");

            while(true) {
                Socket socket = serverSocket.accept();
                System.out.println("----------------------------------------------------------------------------------------------------");
                System.out.println("Communication accepted: " + socket.getInetAddress().getHostAddress() /*+ "\n"*/);
                Server server = new Server(socket);
                Thread t = new Thread(server);
                t.start();

            }


        }catch(Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
        }


    }




    ServerProtocol Comunicao = new ServerProtocol();

    public void run() {


        ObjectInputStream input;

        try {
            input = new ObjectInputStream(server.getInputStream());

            String Msg = (String) input.readObject();
            System.out.println(Msg);

            if (Msg.equals("Start")) {

                System.out.println("Start");



                return;

            }



            if(Msg.equals("Validate")) {

                String typeS = (String) input.readObject();
                System.out.println("Type: " + typeS);

                int x = (int) input.readObject();
                System.out.println("X: " + x);

                int y = (int) input.readObject();
                System.out.println("Y: " + y);

                int rotation = (int) input.readObject();
                System.out.println("Rotation: " + rotation);


                boolean answer = Comunicao.MsgValidate(typeS, x, y, rotation);


                if(answer == false) {

                    System.out.println("Invalid move");
                    ObjectOutputStream saida = new ObjectOutputStream(server.getOutputStream());
                    saida.writeObject("Invalid move");

                } else if(answer == true) {

                    System.out.println("Valid move");
                    ObjectOutputStream saida = new ObjectOutputStream(server.getOutputStream());
                    saida.writeObject("Valid move");

                }


            }



        }catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }





    }



}

我认为错误可能是因为它没有初始化,而是在服务器协议代码的开头做了。错误堆栈跟踪是:

Exception in thread "Thread-1" java.lang.NullPointerException
    at Servidor.ServerProtocol.MsgValidate(ServerProtocol.java:224)
    at Servidor.Server.run(Server.java:138)
    at java.base/java.lang.Thread.run(Thread.java:830)

【问题讨论】:

  • 尝试使用调试器,或使用helpful NPE 找出什么是空的。
  • 错误在第 224 行,但您提供的代码只有 92 行。如果我们是新的,它将在哪条线上崩溃,这将是一个很大的帮助。请用评论标记它:)

标签: java nullpointerexception communication


【解决方案1】:

您面临的问题是因为您使用== 比较java.lang.String,它检查引用是否相等。 因为没有满足您的条件,所以您的方法 MsgValidate 中的变量 type 保持在 null

要解决这个具体问题,请将所有== 检查替换为typeS.equals(TileType.TypeI.toString())。但是,您显示的代码中还有其他几个缺陷。

陷阱

服务器协议:

  1. 您没有在构造函数中初始化成员变量type。您只是创建了一个名为 type 的局部变量,它没有被使用
  2. 成员变量type 应该只是MsgValidate 方法中的局部变量
  3. 您永远不会初始化您的tiles 数组,也永远不会写入它。瓷砖永远不会被占用
  4. 您的ifs 序列可以用一个简单的for循环替换

应用了建议的更改:

package Servidor;


import Servidor.TileType;



// Server side protocol

public class ServerProtocol {

    private static final TileType[] TILE_TYPES = new TileType[]{
        TileType.TypeI, TileType.TypeJ, TileType.TypeL, TileType.TypeO, TileType.TypeS, TileType.TypeT, TileType.TypeZ
    };

    //HighScore HighScore = null;
    //private HighScore hs;
    DataPlayer dataPlayer;// = null;

    private TileType[][] tiles;

    private int lines, score, newLevel, level;



    public ServerProtocol(){
    }



    public boolean MsgValidate(String typeS, int x, int y, int rotation) {
        TileType type = null;

        for (int i = 0; i < TILE_TYPES.length && type == null; i++) {
            if (typeS.equals(TILE_TYPES[i].toString())) {
                type = TILE_TYPES[i];
            }
        }

        if (type == null) {
            // or throw an IllegalArgumentException
            return false;
        }

        if(x < -type.getLeftInset(rotation) || x + type.getDimension() - type.getRightInset(rotation) >= 10) {
            return false;
        }

        if(y < -type.getTopInset(rotation) || y + type.getDimension() - type.getBottomInset(rotation) >= 22) {
            return false;
        }

        for(int col = 0; col < type.getDimension(); col++) {
            for(int row = 0; row < type.getDimension(); row++) {
                if(type.isTile(col, row, rotation) && isOccupied(x + col, y + row)) {
                    return false;
                }
            }
        }
        return true;

    }


    private boolean isOccupied(int x, int y) {
        if (tiles == null) {
            return false;
        } else if (y < 0 || y >= tiles.length) {
            return false;
        } else if (x < 0 || x >= tiles[y].length) {
            return false;
        }

        return tiles[y][x] != null;
    }
}

此外,您应该阅读一些常见的 Java 代码约定。 例如,包应该完全小写。方法名应以小写字母开头

【讨论】:

  • 您的解决方案解决了这个问题,但我在服务器协议的 isOccupied(int x, int y) 上遇到了另一个 NullPointerException。我很想说那些坐标没有被占用。你如何解决这个问题?另外,您在代码中发现了哪些其他陷阱?
  • @Peter 我添加了一些陷阱和解释。希望对你有帮助
  • 您的笔记很有帮助。对于第三个,在与服务器连接后,磁贴将在 for 循环中启动。现在它运行没有错误,但是当服务器回答“有效移动”时,客户端不会继续执行它应该更新行并重新绘制的代码。会不会和连接时间有关?我认为它应该起作用,因为来自服务器的答案存储在一个变量中,连接关闭,如果答案有效,则客户端增加行并重新绘制。你知道问题可能是什么吗?
  • 没关系,我修好了。你能相信我在.equals() 中再次使用“==”吗?啊啊啊。谢谢你,你一直很有帮助!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 2014-02-27
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多