在索引0处访问数组会正确返回,但在索引1+处访问会产生错误吗?

时间:2013-06-20 21:22:15

标签: java arrays

以下是代码:

System.out.println("[Server] Handshake Recieved");

String fdata = new String(p.getData());
String[] data = fdata.split(";");

System.out.println(fdata);
System.out.println(data.length);
System.out.println(data[0]);

p是我制作的Packet类的名称。 getData()返回一个我可以确认总是正确返回的字节数组。

当此代码与data [0]一起运行时,这是控制台输出:

CID;0;Username;Dummy
4
CID

但是当我用数据[1]运行它时,会发生这种情况:

<blank>
1
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 1
    at server.S_GameLoop.parseData(S_GameLoop.java:122)
    at server.S_GameLoop.Update(S_GameLoop.java:87)
    at server.S_GameLoop.Running(S_GameLoop.java:66)
    at server.S_GameLoop.run(S_GameLoop.java:157)
    at java.lang.Thread.run(Thread.java:724)

我不知道为什么会这样。也许你们其中一个人知道答案?

编辑: 这是包含有问题代码的函数:

private void parseData(Packet p, DatagramPacket recievePacket) throws IOException, MethodNotOverridenException {
    switch (p.getTagAsString()) {
    case "LGN_RQS":
        System.out.println("[Server] Login Request Recieved");
        //Login was accepted
        //Create a Client ref, and add it to the vector
        S_Client newClient = new S_Client(recievePacket.getAddress(), recievePacket.getPort());
        ClientList.add(newClient);

        //Create a player and add it to Entity list
        Player newPlayer = new Player(IDGenerator.getAndIncrement(), ClientList.indexOf(newClient));
        EntityMap.put(newPlayer.getEntID(), newPlayer);
        System.out.println("[Server] Created new Player with EID " + newPlayer.getEntID() + " and CID " + newPlayer.getCID());
        //Send reply to Client that is logging in
        sendData(new Packet((byte)2, "LGN_ACP".toCharArray(), ("CID;" + ClientList.indexOf(newClient) + ";EID;" + newPlayer.getEntID()).getBytes()).getBytes(), newClient.getIp(), newClient.getPort());
        //New Entity was created
        sendData(newPlayer.onCreate(this));
    case "HND_SHK":
        System.out.println("[Server] Handshake Recieved");

        String fdata = new String(p.getData());
        String[] data = fdata.split(";");

        System.out.println(p.getData()); //[B@170ad4d5
        System.out.println(fdata);
        System.out.println(data.length);
        System.out.println(data[0]);

        /*S_Client c = ClientList.get(Integer.parseInt(data[1]));
        c.setUsername(data[3]);
        System.out.println("[Server] Set Client " + data[1] + "'s user to " + data[3]); */
    }
}

这是Packet.java:

public class Packet {
private byte ID;
private char[] Tag;
private byte[] Data;

public Packet(byte ID, char Tag[]) {
    this.ID = ID;
    if(Tag.length <= 7)
        this.Tag = Tag;
    else
        throw new IllegalArgumentException("Tag must be at most 7 characters long");
    this.Data = new byte[1];
}

public Packet(byte ID, char Tag[], byte[] Data) {
    this.ID = ID;
    if(Tag.length <= 7)
        this.Tag = Tag;
    else
        throw new IllegalArgumentException("Tag must be at most 7 characters long");
    this.Data = Data;
}

/*
 * Returns the packet ID
 */
public byte getID() {
    return ID;
}

/*
 * Return's the packet TAG
 */
public char[] getTag() {
    return Tag;
}

public String getTagAsString() {
    return new String(Tag);
}

public byte[] getData() {
    return Data;
}

public byte[] getBytes() {
    byte[] c = {ID};
    return concat(c, concat(new String(Tag).getBytes(), Data));
}

public byte[] concat(byte[] A, byte[] B) {
       int aLen = A.length;
       int bLen = B.length;
       byte[] C= new byte[aLen+bLen];
       System.arraycopy(A, 0, C, 0, aLen);
       System.arraycopy(B, 0, C, aLen, bLen);
       return C;
}

}

第二次修改

一点澄清。我运行程序两次。一次使用数据[0],一次使用数据[1]。每次我运行它。它们都产生完全相同的个体结果。 data [0]将始终返回

CID;0;Username;Dummy
4
CID

哪个是对的。但是,使用数据[1]交换数据[0]将始终返回

**<blank>
1**
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 1
    at server.S_GameLoop.parseData(S_GameLoop.java:122)
    at server.S_GameLoop.Update(S_GameLoop.java:87)
    at server.S_GameLoop.Running(S_GameLoop.java:66)
    at server.S_GameLoop.run(S_GameLoop.java:157)
    at java.lang.Thread.run(Thread.java:724)

最终修改 如果有人以某种方式遇到这个问题。问题是我伪造在我的switch语句中添加break;

3 个答案:

答案 0 :(得分:3)

仔细查看第二个日志输出。在程序的第二次运行中,fdata String为空,因此第一行是<blank>。当您使用';'标记空白字符串时,您将获得一个标记,也是一个空字符串。因此,日志的第2行为1(令牌数组中包含1个元素)。然后尝试索引索引1处的令牌数组(它访问数组的SECOND元素);索引0中只有一个元素,因为数组的长度为1.因此,如异常所示,您的索引超出范围。

看起来程序中的真正错误是p.getData()有时会返回一个空字符串。这表明你的“确认[数据包]总是正确返回”的逻辑有一个错误。

答案 1 :(得分:2)

很明显。您的不同测试确实使用了从p.getData()收到的不同数据。

在第一次测试时,您的方法p.getData()返回一个好的String来处理。第二个测试,你有一个空字符串(大小为0),这不是你所期望的。因此,请查看您提供的代码,并搜索p.getData()确实返回不同内容的原因。

答案 2 :(得分:-1)

您的数组只有一个元素,很可能是因为split会删除尾随的空字符串(如果有的话)。 array[1]尝试访问不存在的第二个元素。